使用Shuffle + ballot + popc仅在Warp中的选定通道中写入数据

时间:2016-08-23 17:31:01

标签: multithreading cuda

我在尝试保存一些共享内存以改善处理时遇到了一些问题。在此代码中,每个线程从主机中选择一个模板索引(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;
        }
    }
}

提前感谢!

1 个答案:

答案 0 :(得分:0)

感谢所有支持!

阅读@njuffa并测试代码变体后,它可以正常工作。

以前用于对laneID进行位掩码的方法是不正确的 使用exp2f只产生第一道和最后一道的预期结果。

<强> tAlive = exp2f(laneID + 1)

被替换为:

<强> tAlive = 0xffffffff >> (warpSize - laneID);

所以,现在它起作用,就好了。

修改: 今天我偶然发现post in Parallel for ForALL很好地解释了如何使用shuffle,ballot和popc来过滤导致主要结果的线程。

我希望这个编辑可以帮助别人找到它,因为我过去没有。

此致