第二章
3.使用二维网格和一维块对矩阵求和
那么刚才使用了一维网格一维块的结构来对矩阵进行求和,现在我们来尝试着用二维网格一维块的结构来进行矩阵求和的运算。
二维网格一维块的结构如下:
那么也就是一个线程处理一个对应的矩阵元素。
线程的内存索引依然满足:idx=iy*nx+ix;
依葫芦画瓢嘛,我们可以写出使用二维网格一维块的核函数
__global__ void sumMatrixOnGPUMix(float *MatA,float *MatB,float *MatC,int nx,int ny)
{
unsigned int ix=threadIdx.x+blockIdx.x*blockDim.x;
unsigned int iy=blockIdx.y;
unsigned int idx=iy*nx+ix;
if(ix<nx&&iy<ny)
MatC[idx]=MatA[idx]+MatB[idx];
}
因为线程本身没有y方向上的量,所以iy并不会加上threadIdx.y,而块是一维的,所以blockDim.y缺省为1,可以省略。
设置块和网格的大小
dim3 block(32);//x方向上有32个线程的块
dim3 grid((nx+block.x-1)/block.x,ny);//x方向上创建可以容纳nx个线程的k个块,其中k=nx/block.x的向上取整。y方向上创建可以容纳ny的线程的ny个块。
还是用上次的代码,跑一下这个结果
该代码稍微有点变动,使用CPU时钟频率来获得更精确的时间花销计算。
使用这个修改过的代码来修改2-7,2-8,得到二维网格二维块,一维网格一维块,二维网格一维块的运行时间(Release模式):
由此,我们得出结论:
1.传统的(也就是朴素的)核函数内存分割布局方式不一定能获得最佳性能。
2.改变传入的global memory布局对核函数的性能有不同的影响。
3.多试几种布局方式可能能获得更好的性能。
附:CPU计算该矩阵求和的时间:
可以看到,布局不好的时候,GPU甚至会比CPU慢上许多。