我正在尝试对具有452591个元素的数组执行总和缩减,所有这些都设置为1,因此总和应为452591.
我计算线程数nThreads
作为2的下一个幂,所以它是524288.在while循环的每次迭代中,只有第一半的线程应该工作,在它们的第i个时加元素另一半的价值。只有在nvalues
上设置的元素数组中存在实际值时才会添加。
它适用于127,1025,1072甚至8271个元素。但不是452591,我可以得到原因。 452591元素的光输出为88064。
__global__ void sum_kernel(int nvalues, double nThreads, double *values)
{ int i = blockIdx.x * blockDim.x + threadIdx.x;
while (nThreads > 1)
{ int middle = nThreads / 2;
int j = i + middle;
if ( i < middle )
{ if (j < nvalues )
{ values[i] += values[j]; }
else
{ values[i] += 0; }
}
__syncthreads();
nThreads = middle;
}
if (i == 0)
printf("T0 ------> %0.f \n", values[0] );
}
我的猜测有时候一些theads会在他们不应该添加0时...或者我可能错误地得到了线程ID?
有关更多细节,我将下一次2的幂计算为:
int expo = ceil(log(n) / log(base));
double next2Pow = (double) pow(base, expo)
使用1个dim块和MAX_TPB = 1024
调用内核:
sum_kernel<<< ceil(next2Pow/MAX_TPB), MAX_TPB >>> (nvalues, next2Pow, values_device);
另外,我已检查过设备数组中的值是否正确,因为我可以将它们复制到主机数组,并在主机中正确获取总和。
但是由于学习原因,我希望内核能够正常工作。
答案 0 :(得分:1)
CUDA的减少总额有什么问题?
在CUDA中,与内核启动相关联的线程(网格)并非全部以锁步方式一起执行。 CUDA execution takes place by blocks。
您尝试将整个数据集削减一半的方法取决于让网格中的所有线程协同工作。您可能也会认为__syncthreads()
同步网格中的所有线程(这会使这成为可能),但事实并非如此。它只有operates at the block level。
如果你想学习如何在CUDA中快速并行缩减,而不是进一步剖析这一点,一个好的起点是this treatment of it并且有一个CUDA sample code提供了一个完整的工作实施演示文稿中涵盖的各种方法。