CUDA线程似乎不同步

CUDA线程似乎不同步,cuda,Cuda,我有一个问题,即即使我使用的是syncthreads,但一个线程似乎落后于其他线程。下面的摘录摘自一个大型程序,我已经尽可能地删去了其中的内容,但它仍然再现了我的问题。我发现,在运行此代码时,test4变量不会为所有线程返回相同的值。我的理解是,使用TEST_FLAG变量应该将所有线程引入if(TEST_FLAG==2)条件,因此数组test4中的每个元素都应该返回43的值。然而,我发现所有元素都返回43,除了返回0的线程0。看起来好像这些线程并没有全部到达相同的同步线程。我已经执行了许多测试,

我有一个问题,即即使我使用的是syncthreads,但一个线程似乎落后于其他线程。下面的摘录摘自一个大型程序,我已经尽可能地删去了其中的内容,但它仍然再现了我的问题。我发现,在运行此代码时,test4变量不会为所有线程返回相同的值。我的理解是,使用TEST_FLAG变量应该将所有线程引入
if(TEST_FLAG==2)
条件,因此数组test4中的每个元素都应该返回43的值。然而,我发现所有元素都返回43,除了返回0的线程0。看起来好像这些线程并没有全部到达相同的同步线程。我已经执行了许多测试,我发现删除更多的代码,例如Yuta提到的(l=0;l)的
\uuuSyncThreads()
行为没有在条件语句中定义。因此,在那里可能/可能无法按预期工作。您可能需要重新编写代码,以避免获得
\uSyncThreads()
输入您的if条件

有关
\uuu syncthreads()
的更多信息,请查看和


还需要注意的是,它是一个块级屏障。您不能使用
\uuuu syncthreads()同步不同的块
。块必须通过内核调用进行同步。

您的问题在于语句TEST\u FLAG=99。对于其中一个线程,它在线程0进入条件块之前执行,并为您提供未定义的行为。如果我注释掉TEST\u FLAG=99,代码将按预期运行。

\u synchthreads()在条件语句中可能没有用户定义的行为,即使所有线程都在同一个代码块中。我给出的一个示例给人的印象是,只有当所有线程都不遵循同一个分支时才会出现问题,就像您链接的示例中那样。在我的示例中,所有线程都遵循相同的路径,所以我会不希望syncthreads出现任何问题在条件代码中是允许的,但前提是条件在整个线程块中的计算结果相同,否则代码执行可能会挂起或产生意外的副作用。请提供完整的复制器,而不仅仅是内核?我不知道您的启动配置是什么,以及其他详细信息,我不知道而不是猜测。这绝对是wierd代码。例如,在初始化条件之前,您正在条件中使用
boundary[0]
的值。请注意,SO要求:“关于您编写的代码问题的问题必须在问题本身中描述具体问题,并包括重现问题的有效代码。请参阅SSCCE.org以获取指导。”我在特斯拉C2075卡上使用python 2.7.3中的pycuda(2011,2,2版)运行此程序。我使用(64,1,1)、网格(200,0,0)块运行它。但它们对结果没有任何影响,test4和test5是长度等于线程数的数组。我用整个python脚本替换了上述代码,包括对缺少边界的修改[0]初始化我一定是无意中从原始版本中删除的。我希望这些信息有帮助。如果您需要更多信息,请告诉我。我相信我已经复制了这个问题(尽管我没有使用python)同时,我相信如果你能告诉pyCUDA将
-G
传递给
nvcc
编译器,你也许能够解决这个问题。我不知道怎么做,但我认为在某处找到答案应该很容易。你的代码可能会运行得比较慢,使用
-G
开关。正如我提到的d在我对Yuuta的回复中,《CUDA编程指南》(第B.6节),“
\uu syncthreads()
在条件代码中是允许的,但前提是条件代码在整个线程块中的计算结果相同,否则代码执行可能会挂起或产生意外的副作用。“上面的示例代码在整个代码块中的计算结果是相同的,因此没有线程分歧。这在您提到我的论文中也进行了重复,该论文重点讨论了线程分歧的情况。除非我误解了它。我生成了一个更简单的测试用例,它再现了相同的问题,并且没有
\uuSyncThreads()的实例。”
在一个条件中,所以我同意这不是问题所在。我意识到如果没有
TEST\u FLAG=99
线程都会返回相同的值,这就是为什么我在那里有一个测试标志。它用于确定由于某种原因,并非所有线程都在
TEST\u FLAG=99
上方的行上同步,这应该ld影响所有线程进入
if(TEST\u FLAG==2)
条件语句,并在
TEST\u FLAG
共享变量更改之前将一个数字写入test4,然后同步。我同意所有线程都应该进入if(TESTFLAG==2)if(TEST\u FLAG==2)但是,当我在此块之前添加以下print语句时:
printf(“testflag%u%u\n”,threadIdx.x,TEST\u FLAG);
,它显示线程0将TEST\u FLAG设置为99,而其他所有线程都将其设置为2,因此线程0最终不会进入该块。
import numpy as np
import pycuda.driver as drv
import pycuda.compiler
import pycuda.autoinit
import pycuda.gpuarray as gpuarray
import pycuda.cumath as cumath
from pycuda.compiler import SourceModule

gpu_code=SourceModule("""
    __global__ void test_sync(double *test4, double *test5)
    {
        __shared__ double rad_loc[2], boundary[2], boundary_limb_edge[2];
        __shared__ int TEST_FLAG;
        int l;


        if (blockIdx.x != 0)
        {
            return;
        }

        if(threadIdx.x == 0)
        {
            TEST_FLAG = 2;
            boundary[0] = 1;
        }

        test4[threadIdx.x] = 0;
        test5[threadIdx.x] = 0;

        if (threadIdx.x == 0)
        {
            rad_loc[0] = 0.0;
        }
        __syncthreads();

        for (l=0; l<1; ++l)
        {
            __syncthreads();
            if (rad_loc[0] > 0.0)
            {
                test5[threadIdx.x] += 1;

                if ((int)boundary[0] == -1)
                {
                    __syncthreads();
                    continue;
                }
            }
            else
            {
                if (threadIdx.x == 0)
                {
                    boundary_limb_edge[0] = 0.0;
                }
            }
            __syncthreads();

            if (TEST_FLAG == 2)
            {
                test4[threadIdx.x] = 43;
                __syncthreads();

                TEST_FLAG = 99;
            }
            __syncthreads();

            return;
        }
        return;
    }

    """)


test_sync = gpu_code.get_function("test_sync")

DATA_ROWS=[100,100]

blockshape_data_mags    = (int(64),1, 1)
gridshape_data_mags     = (int(sum(DATA_ROWS)), 1)

test4 = np.zeros([1*blockshape_data_mags[0]], np.float64)
test5 = np.zeros([1*blockshape_data_mags[0]], np.float64)

test_sync(drv.InOut(test4), drv.InOut(test5), block=blockshape_data_mags, grid=gridshape_data_mags)

print test4
print test5