我正在使用共享内存为学校编写程序。我得到了正常工作的功能,但它只适用于每网格大小为1的块。如果每个网格有超过1个块,则该功能不再起作用。
例如,如果我发送一个大小为10的数组,包含1个块和10个线程,则此功能可正常工作。如果我发送相同的数组,每个块有2个块和5个线程,那么它就不再有效了。当我说不再有效时,我会收到我发送的相同阵列,退出,就像什么也没发生一样。
__global__ void rankSortShared(int* a, int n)
{
int threadId = threadIdx.x + blockDim.x * blockIdx.x;
int x = 0;
// Make dynamic sized shared array
// size will be determined from the 3rd parameter in the
// kernal call 'ranksortShared<<<blocksPerGrid, threadsPerBlock, *(size of shared mem)*>>>()'
extern __shared__ int b[];
// copy data from incomming array to shared array
// then sync the threads so all threads have put their
// values into the shared array
b[threadId] = a[threadId];
__syncthreads();
// now use shared array for faster lookups
for (int j = 0; j < n; j++)
{
// handle duplicate values
if (b[j] < b[threadId] || (b[threadId] == b[j] && j < threadId))
{
x++;
}
}
// put data back into array to be transferred back to CPU
a[x] = b[threadId];
}
对于我的生活,我无法弄清楚为什么。是否有一种特殊的方法可以在多个块中使用共享内存?
为了尝试调试这个,我用a[threadId] = threadId
替换了所有代码,并且数组看似正确(打印数字0到9)。所以,我不明白为什么如果threadId似乎是正确的,这不会起作用,并且它适用于1个块。
答案 0 :(得分:2)
这里有一个问题:
int threadId = threadIdx.x + blockDim.x * blockIdx.x;
b[threadId] = ...;
您的threadId
变量是全局唯一的线程索引。这意味着你在网格中包含的线程越多(例如通过更多的块),这个索引就越高。
但对于共享内存,每个块中的索引从零开始。因此,最终,当您添加更多块时,您的threadId
变量将大于块中的共享内存量。
通常的解决方案是做这样的事情:
b[threadIdx.x] = ...;
因为threadIdx.x
变量从每个块中的零开始。 (您可以使用此策略将{{>>每个出现的b[threadId]
替换为b[threadIdx.x]
,而不仅仅是一次。)
您的代码中可能还有其他问题。由于您还没有显示完整的代码,因此无法诊断其他代码。
基于这样的陈述:
当我说不再有效时,我会收到我发送的相同阵列,退出,就像什么也没发生一样。
我的猜测是你没有做proper cuda error checking。在向别人寻求帮助之前,你应该真的这样做。即使你不理解错误输出,它也会帮助其他人试图帮助你。