本文用作学习笔记,仅做参考。
代码实现D=A*B+C的矩阵运算,A与B分别为n*m与m*n矩阵.
具体如下(本代码所用语言为C++):
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#include <offload.h>
//定义矩阵A的行数(N)与列数(M)
#define N 5
#define M 5
//检测是否在mic上运行
__attribute__((target (mic)))
void offload_check(void)
{
#ifdef __MIC__
printf("check func:Run on the mic!\n");
#else
printf("check func;Run on the cpu!\n");
#endif
}
//矩阵加法
__attribute__((target (mic)))
void MatAdd(float** A,float** B,float** C,int n,int m)
{
offload_check();
#pragma omp parallel //num_threads(set_omp_num_threads)
{
#pragma omp for
for (int i=0;i<n;i++)
{
for (int j=0;j<m;j++)
C[i][j]=A[i][j]+B[i][j];
}
}
}
//矩阵乘法
__attribute__((target (mic)))
void MatMulti(float** A,float** B,float** C,int n,int m)
{
offload_check();
#pragma omp parallel //num_threads(set_omp_num_threads)
{
#pragma omp for
for (int i=0;i<n;i++)
{
for (int j=0;j<n;j++){
C[i][j]=0.0;
for (int k=0;k<m;k++)
{
C[i][j] += A[i][k] * B[k][j];
}
}
}
}
}
int main( int argc,char** argv)
{
int i,j;
float *in1;
float **A,**B,**C,**D,**E,**F;
//分配内存
A=(float**)malloc(sizeof(float*)*N);
for(int i=0;i<N;i++)
A[i]=(float*)malloc(sizeof(float)*M);
B=(float**)malloc(sizeof(float*)*M);
for(int i=0;i<M;i++)
B[i]=(float*)malloc(sizeof(float)*N);
C=(float**)malloc(sizeof(float*)*N);
for(int i=0;i<N;i++)
C[i]=(float*)malloc(sizeof(float)*N);
D=(float**)malloc(sizeof(float*)*N);
for(int i=0;i<N;i++)
D[i]=(float*)malloc(sizeof(float)*N);
E=(float**)malloc(sizeof(float*)*N);
for(int i=0;i<N;i++)
E[i]=(float*)malloc(sizeof(float)*N);
F=(float**)malloc(sizeof(float*)*N);
for(int i=0;i<N;i++)
F[i]=(float*)malloc(sizeof(float)*N);
//对A,B,C矩阵进行初始化
for (int i=0;i<N;i++)
{
for (int j=0;j<M;j++)
{
A[i][j]=i+1;
B[j][i]=i+2;
}
}
for (int i=0;i<N;i++)
{
for (int j=0;j<N;j++)
{
C[i][j]=i+3;
}
}
#pragma offload target(mic:0) in(A:length(N)) in(B:length(M)) inout(E:length(N)) signal(in1)
{
MatMulti(A,B,E,N,M);
}
for (int i=0;i<N;i++)
{
for (int j=0;j<N;j++)
F[i][j]=E[i][j];
}
#pragma offload target(mic:0) in(F,C:length(N)) out(D:length(N)) signal(in1)
{
MatAdd(F,C,D,N,N);
}
//check the result
for (int i=0;i<N;i++)
{
for (int j=0;j<N;j++)
printf("%d,%d,%f\n",i,j,D[i][j]);
}
//释放内存
free(A);
free(B);
free(C);
free(D);
free(E);
free(F);
}
代码尚待完善,目前发现的不足如下:
-
尚未知晓
#pragma
语句中signal
传参的作用为何,只是若是不加signal
参数,调试时会出现:```cpp offload error :process on the device 0 was terminated by signal 11 ```
代码改来改去不得其法,没办法只好暂时这般勉强处理。
-
本代码实现的是D=A*B+C矩阵运算,运算方式是:E=A*B,F=E,D=F+C,E,F作为辅助矩阵,实际上占用了大量无用的内存。
如果说E是作为加法与乘法的函数转换的中间量有其存在的意义的话,F就完全是没有大的存在必要的,可以去掉。
至于中间量E,实际上也是可以去除的:实际上可以将加法与乘法合并到一个函数中进行。 -
矩阵是在程序中事先初始化的,结果暂时就通过printf打印,欲使代码实际可用,还需根据实际情况进行修改。