循环常量会产生错误的结果

时间:2013-11-01 11:30:33

标签: c for-loop cuda

我即将为CUDA设备编写直方图内核。它基于NVIDIA's paper

这个想法是每个线程计算某个部分的部分直方图(在我的情况下是一个卷)并将其写入共享内存块。但是,我在算法中遇到了一个奇怪的问题,并将内核剥离到重要部分:

__global__ void calcHist64()
{
    extern __shared__ unsigned char partialHistograms[];

    //a unique sequential thread id within this block, used to determine the memory in which to write the partial histogram
    unsigned int seqTid = threadIdx.x + threadIdx.y * blockDim.x;       
#pragma unroll
    for(int i = 0; i < 255; ++i)
    {
        //increment the thread's partial histogram value
        partialHistograms[seqTid]++; 
    }
    //each partial histogram should now be 255
    //Output the value for every thread in a certain block
    if(blockIdx.x == 0 && blockIdx.y == 31)
        printf("Partial[%i][%i]: %i\n", threadIdx.x, threadIdx.y, partialHistograms[partialHistRoot]);  
}

通过以下方式调用内核:

int sharedMemory = 4096;
dim blocks(32, 32, 1);
dim3 threadsPerBlock(8,8,1);
calcHist64<<<blocks, threadsPerBlock, sharedMemory>>>();

我希望每个部分直方图的值都为255.但是,这仅适用于前几个块(低blockIdx.x / blockIdx.y)。其他块的值差别很大。最后一个块(blockIdx.y == 31)的值为239或240。

我无法解释这种行为。它是一个常量for循环,毕竟运行了255次。每个线程访问共享内存的不同部分,因此不应存在竞争条件。

任何人都可以解释这种行为吗?

1 个答案:

答案 0 :(得分:3)

您没有初始化共享内存。它不会自动初始化为零。

在这行代码之后:

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

添加:

partialHistograms[seqTid] = 0;

同样在您的代码中,您没有定义partialHistRoot。我假设partialHistRoot == seqTid。如果不是这种情况,那么你就有竞争条件和你的陈述

  

每个线程访问共享内存的不同部分,因此不应存在竞争条件。

不正确。