总结了MKL函数库中矩阵相乘在C语言中的运用子函数。注意:mkl函数库得将二维矩阵转为一维矩阵(按行排序)进行计算。
1、官方给的原理
矩阵与矩阵的乘法,分为双精度的cblas_sgemm和单精度的cblas_sgemm,两个函数的参数意义一样,只是类型不一样
运算式:C=alpha*A*B+beta*C
一般取alpha=1.0,beta=0.0 即计算式:C=A*B
cblas_sgemm(CblasRowMajor, CblasNoTrans,CblasNoTrans,M,N,K,alpha,A,A的列数,B,B的列数,beta,C,C的列数)
CblasRowMajor表示数组时行为主,相应矩阵大小为(MK)乘以(KN),可以得到M,K,N的值
前面的CblasNoTrans表示A是否转置,后面表示B是否转置,即可以表示A(T)B=C或者AB(T)=C或者A(T)*B(T)=C,如果是A的转置乘以B,M,N是A的转置的行数和列数
cblas_sgemm(CblasRowMajor, CblasNoTrans,CblasNoTrans,M,N,K,alpha,A,A的列数,B,B的列数,beta,C,C的列数)
矩阵与向量的乘法,同样有两个cblas_sgemv和cblas_dgemv
运算式:C=alphaAb+beta*C
一般取alpha=1.0,beta=0.0 即计算式:C=A*b
cblas_sgemv(CblasRowMajor, CblasNoTrans,A的行数,A的列数,alpha,A,A的列数,b,1,beta,C,1)
如果是A的转置*b,用
cblas_sgemv(CblasRowMajor, CblasTrans,A的行数,A的列数,alpha,A,A的列数,b,1,beta,C,1)
2、自己代码
完成普通两个二维矩阵的相乘运算:Aa*Bb=Cc
matrix_mult.c
/*********************************************************************************************************
1.此子程序主要是用于求解矩阵的相乘
2.参数说明
传入的参数:二维数组Aa,Bb,维数int M, int K, int N
传出的参数:
*********************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "mkl.h"
double ** matrix_mult(double **Aa, double **Bb, int M, int K, int N)
//M为A矩阵的行数;K为矩阵A的列数;N为矩阵B的列数
{
const enum CBLAS_ORDER Order = CblasRowMajor;
const enum CBLAS_TRANSPOSE TransA = CblasNoTrans;
const enum CBLAS_TRANSPOSE TransB = CblasNoTrans;
int i, j, mm, nn;
double alpha = 1.0;
double beta = 0.0;
double * A;
double * B;
double * C;
double ** end_C;
int lda = K; //A的列
int ldb = N; //B的列
int ldc = N; //C的列
int A_num = M * K;
int B_num = K * N;
int C_num = M * N;
//动态定义一维数组
A = (double*)malloc(sizeof(double) * A_num);
B = (double*)malloc(sizeof(double) * B_num);
C = (double*)malloc(sizeof(double) * C_num);
//动态定义二维数组
end_C = (double**)malloc(sizeof(double*) * N);
for (i = 0; i < N; i++)
{
end_C[i] = (double*)malloc(sizeof(double) * M);
}
//矩阵初始化
for (i = 0; i < M * K; i++)
{
A[i] = 0.0;
}
for (i = 0; i < N * K; i++)
{
B[i] = 0.0;
}
for (i = 0; i < M * N; i++)
{
C[i] = 0.0;
}
for (i = 0; i < N; i++)
{
for (j = 0; j < M; j++)
{
end_C[i][j] = 0.0;
}
}
//二维矩阵Aa按行内容转为一维矩阵
mm = 0;
for (i = 0; i < M; i++)
{
for (j = 0; j < K; j++)
{
mm = i * K + j;
A[mm] = Aa[i][j];
}
}
//二维矩阵Bb按行内容转为一维矩阵
nn = 0;
for (i = 0; i < K; i++)
{
for (j = 0; j < N; j++)
{
nn = i * N + j;
B[nn] = Bb[i][j];
}
}
//MKL函数库矩阵相乘
cblas_dgemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
for (i = 0; i < M; i++)
{
for (j = 0; j < N; j++)
{
end_C[j][i] = C[i*N + j]; //一维矩阵转二维矩阵,并完成转置工作
}
}
//释放
free(A); A = NULL; free(B); B = NULL; free(C); C = NULL;
return end_C;
for (i = 0; i < N; i++)
{
free(end_C[i]); end_C[i] = NULL; /*释放列*/
}
free(end_C); end_C = NULL; /*释放行*/
}