仅分配了共享内存阵列的一半

时间:2015-01-29 21:55:48

标签: cuda shared-memory nsight

我看到只有一半的共享内存数组被分配,当我在s_f[sidx] = 5;

之后使用Nsight时
__global__ void BackProjectPixel(double* val,   
                                    double* projection,
                                    double* focalPtPos,
                                    double* pxlPos,
                                    double* pxlGrid,
                                    double* detPos, 
                                    double *detGridPos,
                                    unsigned int nN,
                                    unsigned int nS,
                                    double perModDetAngle,
                                    double perModSpaceAngle,
                                    double perModAngle)                 
{
    const double fx = focalPtPos[0];
    const double fy = focalPtPos[1];

    //extern __shared__ double s_f[64]; // 

    __shared__ double s_f[64]; // 

    unsigned int i = (blockIdx.x * blockDim.x) + threadIdx.x;
    unsigned int j = (blockIdx.y * blockDim.y) + threadIdx.y;
    unsigned int idx = j*nN + i;

    unsigned int sidx = threadIdx.y * blockDim.x + threadIdx.x;

    unsigned int threadsPerSharedMem = 64;

    if (sidx < threadsPerSharedMem)
    {
        s_f[sidx] = 5;
    }

    __syncthreads();

    //double * angle;
    //

    if (sidx < threadsPerSharedMem)
    {

        s_f[idx] = TriPointAngle(detGridPos[0], detGridPos[1],fx, fy, pxlPos[idx*2], pxlPos[idx*2+1], nN);
    }



}

这是我观察到的

enter image description here

我想知道为什么只有三十二个5? s_f中不应该有64个5吗?感谢。

2 个答案:

答案 0 :(得分:2)

线程以线程组(通常为32)执行,这些线程也称为warp。 Warps按顺序对线程进行分组。在你的情况下,一个warp将获得0-31的线程,另一个32-63。在调试上下文中,您可能只看到包含线程0-31的warp的结果。

答案 1 :(得分:1)

  

我想知道为什么只有三十二个5?

有32个五,因为正如mete所说,内核只能由大小为32的线程组同时执行,因此在CUDA术语中称为warp。

  

s_f中不应该有64个5吗?

同步障碍后 将是64个五,即__syncthreads()。因此,如果您在__syncthreads()电话后的第一条指令上放置断点,您将看到所有五个。那是因为到那时,来自一个区块的所有warp将完成__syncthreads()之前的所有代码的执行。

  

如何通过Nsight查看所有经线?

通过将其放入监视区域,您可以轻松查看所有线程的值:

s_f[sidx]

虽然sidx值可能因优化而未定义,但我最好注意以下值:

s_f[((blockIdx.y * blockDim.y) + threadIdx.y) * nN + (blockIdx.x * blockDim.x) + threadIdx.x]

事实上,如果你想调查特定warp的值,那么正如Robert Crovella指出的那样,你应该使用条件断点。如果你想在第二个warp中断,那么这样的东西应该适用于二维块的二维网格(我认为你正在使用):

((blockIdx.x + blockIdx.y * gridDim.x) * (blockDim.x * blockDim.y) + (threadIdx.y * blockDim.x) + threadIdx.x) == 32

因为32是第二个warp中第一个线程的索引。有关块和网格尺寸的其他组合,请参阅this useful cheatsheet