CUDA内核似乎无视“if”语句

时间:2013-09-11 09:02:08

标签: c++ visual-studio-2012 cuda nsight

以下是我内核中行为不正常的部分,然后解释了我在调试时发现的内容。

__global__ void Mangler(float *matrix, int *map)
{
    __shared__ signed int localMap[N];

    if(0 == threadIdx.x) 
    {
        for(int i=0; i<N; i++) 
            localMap[i] = -1;
    }

    __syncthreads();

    int fn = ...; // a lot of code goes into this number, skipped for clarity
    int rnumber = threadIdx.x;

    int X = atomicCAS(&localMap[fn], -1, rnumber); // Spot of bother 1

    if(X == -1) // Spot of bother 2
    {
        // some code
    }
    else 
    {
        // other code
    }
}

我在文档中发现atomicCAS(*address, compare, value)基本上返回(并保存到给定地址)(old == compare ? value : old)的结果,其中old是执行函数前地址的值。

对此,我认为执行int X = atomicCAS(&localMap[fn], -1, rnumber);应该有两种可能的结果(根据NVidia Cuda C编程指南):

  • 如果localMap[fn] == -1,则X的值应为rnumberlocalMap[fn]的值应为rnumber这不会发生。
  • 如果localMap[fn] != -1,那么X应设置为localMap[fn]的值,并且该值应保持不变。

相反,正如使用NSight进行的调试所显示的那样,X被分配为-1,而localMap[fn]被赋予rnumber的值。我不明白,但正如您在我的代码中所看到的,我已经更改了if来捕捉这种情况。

这让我想到了第二个问题:尽管NSight将X的值显示为-1,但if {}被完全跳过(在任何命中都没有断点)并且执行直接跳转到else

我的问题:

  • 我是否完全误解了atomicCAS 是的,我做了
  • 在设备代码中直接跳转到if的原因和else哪些应该评估为真?

我在Windows 8上使用NVidia CUDA 5.5,Visual Studio 2012 x64,NVidia Nsight Monitor Visual Studio Edition 3.1。该机器的GPU是NVidia GeForce GTX 550 Ti。

我尝试将语法更改为if(X!=-1); if的真正分支仍未执行。

1 个答案:

答案 0 :(得分:1)

从文档中,atomicCAS返回旧值,这意味着,在您的列表中,您的两个结果是错误的。您的X将始终设置为localMap[fn]的旧值,无论它具有哪个值。根据与-1的比较设置的是localMap[fn]的新值。当它为-1时,它被设置为rnumber,否则它将保持不变。

因此,您使用XrnumberlocalMap的值看到的行为符合预期。

我无法解决你的第二个问题,因为我没有使用NSight,也不知道它是如何工作的 - 根据你的代码,你的真正分支应该被评估(但要小心:你的假分支也是 - 因为它是多线程的有些线程可以将条件评估为true,有些则为false - 我的猜测/假设是你必须以某种方式告诉你的调试器你要调试哪个线程/ warp / block并且你看错了。