CUDA共享内存广播和__syncthreads行为

时间:2013-03-25 15:21:22

标签: cuda

我遇到了一个奇怪的问题,至少在我看来它看起来很奇怪,而且我希望有人能够对它有所了解。我有一个CUDA内核,它依赖于共享内存来进行快速本地访问。据我所知,如果半warp中的所有线程都访问相同的共享内存库,那么该值将被广播到warp中的线程。此外,从多个warp访问同一个bank不会导致银行冲突,它们只会被序列化。牢记这一点,我已经创建了一个小内核来测试它(在遇到原始内核中的问题之后)。这是片段:

#define NUM_VALUES 16
#define NUM_LOOPS  1024

__global__ void shared_memory_test(float *output)
{
    // Create some shared memory
    __shared__ int dm_delays[NUM_VALUES];

    // Loop over NUM_LOOPS
    float accumulator = 0;
    for(unsigned c = 0; c < NUM_LOOPS; c++)
    {
        // Force shared memory update
        for(int d = threadIdx.x; d < NUM_VALUES; d++)
            dm_delays[d] = c * d;

        // __syncthreads();
        for(int d = 0; d < NUM_VALUES; d++)
            accumulator += dm_delays[d];
}

    // Store accumulated value to global memory
    for(unsigned d = 0; d < NUM_VALUES; d++)
        output[d] = accumulator;
}

我运行它的块大小为16(一半经线,效率不是很高,但仅用于测试目的)。所有线程都应该寻址相同的共享内存库,因此不应该有冲突。然而,相反的情况似乎是正确的。我在Visual Studio 2010上使用Parallel Nsight进行此测试。

对我来说更神秘的是,如果我在外部循环中取消注释__syncthreads调用,那么银行冲突的数量会急剧增加。

只是一些数字给你一个想法(这是一个网格包含一个16个线程的块,所以一个半warp,NUM_VALUES = 16,NUM_LOOPS = 1024):

  • 没有__syncthreads:4次银行冲突
  • __syncthreads:4,096次银行冲突

我在GTX 670上运行它,设置为compute_capability 3.0

提前谢谢

更新:有人指出,没有__syncthreads,外部循环中的NUM_LOOPS读取被编译器优化掉,因为dm_delays的值永远不会改变。现在我在这两种情况下都会得到一个持续的4,096个银行冲突,这对于共享内存的广播行为仍然不能很好。

1 个答案:

答案 0 :(得分:0)

由于dm_delays的值没有改变,这可能是如果__syncthreads不存在,编译器会优化1024次读取到共享内存的情况。使用__syncthreads,它可能会假设该值可能被另一个线程更改,因此它会一遍又一遍地读取该值。

相关问题