乘法的形式都一样,都是分配一样的线程,两种形式不同的地方在于处理矩阵大小不同,通过分块的方法解决大矩阵的问题,两种形式的代码如下;
_global_void MatrixMulKernel(float*Md,float *Nd,float *Pd,int Width)
{
//2维线程ID
int tx = threadIdx.x;
int ty = threadIdx.y;
//Pvalue 存储线程计算得到的Pd中的元素
float Pvalue = 0;
for(int k=0;k<Width;++k)
{
float Mdelement = Md[ty*Width+k];
float Ndelement = Nd[k*Width+tx];
Pvalue+=Mdelement*Ndelement;
}
//把矩阵写入设备存储器,每个线程负责写一个元素
Pd[ty*Width+tx]=Pvalue;
}
//设置对应的执行配置参数,dim3类型的struct变量
dim3 dimBlock(Width,Width);//描述块的配置
dim3 dimGrid(1,1);//描述网格的配置信息,一共多少块
第二种方式,分块,怎么分块,分多少块,都可以根据自己的意愿来修改以便应对不同大小的矩阵。
_global_void MatrixMulKernel(float *Md, float *Nd, float *Pd ,int Width)
{
//计算Pd和Md中的元素的行索引和列索引
int Row = blockIdx.y*TILE_WIDTH+threadIdx.y;
int Col = blockIdx.x*TILE_WIDTH+threadIdx.x;
float Pvalue =0;
//每个线程负责计算块子矩阵的一个矩阵
for(int k=0;k<Width;++k)//Width是矩阵的总长度
{
Pvalue+=Md[Row*Width+k]*Nd[k*Width+Col];
}
Pd[Row*Width+Col]=Pvalue;//按行放
}
//设置执行配置参数
dim3 dimGrid(Width/TILE_WIDTH,Width/TILE_WIDTH);每个网格分配多少块
dim3 dimBlock(TILE_WIDTH,TILE_WIDTH);//每个块分配多少个线程
//启动用于计算线程的设备
MatrixMulKernel<<<dimGrid,dimBlock>>>(Md,Nd,Pd,Width)
注意:我觉得这个地方的索引和按列存储还是有些绕,的好好琢磨一下子。