Windows 7, NVidia GeForce 425M.
我编写了一个简单的CUDA代码,该代码计算矩阵的行总和。矩阵具有一维表示形式(指向浮点数的指针)。
代码的串行版本如下(2如预期的那样,它具有循环):
void serial_rowSum (float* m, float* output, int nrow, int ncol) {
float sum;
for (int i = 0 ; i < nrow ; i++) {
sum = 0;
for (int j = 0 ; j < ncol ; j++)
sum += m[i*ncol+j];
output[i] = sum;
}
}
在CUDA代码内部,我调用了内核函数,它按行扫描矩阵。下面是内核调用代码段:
dim3 threadsPerBlock((unsigned int) nThreadsPerBlock); // has to be multiple of 32
dim3 blocksPerGrid((unsigned int) ceil(nrow/(float) nThreadsPerBlock));
kernel_rowSum<<<blocksPerGrid, threadsPerBlock>>>(d_m, d_output, nrow, ncol);
和执行行的并行总和的内核函数(仍然具有1循环):
__global__ void kernel_rowSum(float *m, float *s, int nrow, int ncol) {
int rowIdx = threadIdx.x + blockIdx.x * blockDim.x;
if (rowIdx < nrow) {
float sum=0;
for (int k = 0 ; k < ncol ; k++)
sum+=m[rowIdx*ncol+k];
s[rowIdx] = sum;
}
}
到现在为止还挺好。串行和并行(CUDA)结果相等。
关键是,即使我更改了nThreadsPerBlock参数,CUDA版本几乎花费了计算串行时间两倍的时间:我测试了nThreadsPerBlock从32到1024(我的卡允许的每个块的最大线程数)。
IMO,矩阵尺寸大足以证明并行化:90,000 x 1,000。
下面,我报告使用different的串行和并行版本所花费的时间nThreadsPerBlock。报告msec的平均100样本时间为:
矩阵:nrow = 90000 x ncol = 1000
串行:每次采样的平均时间经过的毫秒(以100样品)289.18。
CUDA(32ThreadsPerBlock):平均时间消逝每样毫秒(在100样本)497.11。
CUDA(1024ThreadsPerBlock):平均时间消逝每样毫秒(在100样本)699.66。
以防万一,带有32/ 的版本1024 nThreadsPerBlock是最快/最慢的版本。
我知道从主机复制到设备以及以其他方式进行复制时会产生某种开销,但是可能速度较慢是因为我没有实现最快的代码。
由于我远非CUDA专家:
我是否为此任务编写了最快的版本?如何改善我的代码?我可以摆脱内核函数中的循环吗?
任何想法表示赞赏。
编辑1
虽然我描述了一个标准rowSum,我有兴趣在AND/ OR具有行操作(0;1}的值,比如rowAND/ rowOR。就是说,正如一些评论员所建议的那样,它不允许我利用“ cuBLAS乘以1”的COL列向量技巧。
编辑2
根据用户的建议,其他用户在这里认可:
忘记尝试编写自己的功能,而是使用Thrust库,魔力来了。
红糖糍粑
相关分类