我在尝试保存一些共享内存以改善处理时遇到了一些问题。在此代码中,每个线程从主机中选择一个模板索引(t_initdwl)并将其扩展到下一个内核处理它之前的上限。
这个想法是使用shuffle + ballot来“保留”适当的空间量,以便只写入未超过上限的线程的索引。由于它是一个限制数组,因此首先测试每个col限制然后写入。 “扩展条目”的数量根据初始索引中的值而变化,但是,一旦线程超过限制,任何进一步的增量都无效,因此它设置play = false(只是为了安全)并返回。
问题是bCol值始终为trasnp_line + 1,这表明popc在此行中无法正常工作,因为1是lineID 0的正确值。我没有收到任何错误,
预期结果是写入行的正确位置,考虑到仍在“播放”(尚未返回)的行数。
__global__ void dwLgen(const int maxthreads, short* __restrict__ kpL, int* nkpl,
const short* __restrict__ init_dwL, const short rloops){
__shared__ short t_initdwl[1024][24];
const int warpID(threadIdx.x / warpSize);
const int laneID(threadIdx.x % warpSize);
const int st(rloops + 2);
const int stb((p - kpMax + 1 + 1) * BUFFERSIZE_MAX);
const int idx = blockDim.x * blockIdx.x + threadIdx.x;
unsigned int cAlive, tAlive, bCol, bline, transp_line;
int i, j;
bool volatile play(true);
if (idx < maxthreads) {
for (j = 0; j < st; j++){
t_initdwl[threadIdx.x][j] = init_dwL[idx + j * BUFFERSIZE_MAX];
}
__syncthreads();
for (i = 0; i < p; i++) {
for (j = 0; j < st; j++)
if ((t_initdwl[threadIdx.x][j] + i) > dwLt[j]) {
play = false;
return;
}
cAlive = __ballot((play == true));
tAlive = __popc(cAlive);
bline = __ffs(cAlive) - 1;
if (laneID == bline)
transp_line = atomicAdd(nkpl, tAlive);
transp_line = __shfl(transp_line, bline);
tAlive = exp2f(laneID + 1);
bline = tAlive & cAlive; // the bline value is ok
bCol = transp_line + __popc(bline); // but __popc(bline) become always 1
for (j = 0; j < st; j++)
kpL[bCol + j * stb] = t_initdwl[threadIdx.x][j] + i;
}
}
}
提前感谢!
答案 0 :(得分:0)
感谢所有支持!
阅读@njuffa并测试代码变体后,它可以正常工作。
以前用于对laneID进行位掩码的方法是不正确的 使用exp2f只产生第一道和最后一道的预期结果。
<强> tAlive = exp2f(laneID + 1)
强>
被替换为:
<强> tAlive = 0xffffffff >> (warpSize - laneID);
强>
所以,现在它起作用,就好了。
修改强>: 今天我偶然发现post in Parallel for ForALL,很好地解释了如何使用shuffle,ballot和popc来过滤导致主要结果的线程。
我希望这个编辑可以帮助别人找到它,因为我过去没有。
此致