我有一个问题,即使我正在使用syncthreads,似乎单个线程落后于其余部分。以下摘录摘自一个大型程序,我尽可能地删除它仍然可以重现我的问题。我发现在运行此代码时,test4变量不会为所有线程返回相同的值。我的理解是使用TEST_FLAG变量它应该引导所有线程进入if (TEST_FLAG == 2)
条件,因此数组test4中的每个元素都应该返回值43.但是我发现所有元素都返回43,除了线程0返回0.看起来好像线程并非都进入相同的syncthreads。我已经进行了大量测试,我发现删除更多代码,例如for (l=0; l<1; ++l)
循环可以解决问题,但我不明白为什么。任何有关为什么我的线程都没有返回相同值的帮助将不胜感激。
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
答案 0 :(得分:1)
正如Yuuta所说,__syncthreads()
行为未在条件语句中定义。因此有它可能/可能不会按预期工作。您可能需要重新编写代码,以避免__syncthreads()
进入if条件。
您可以查看this answer和this paper,了解有关__syncthreads()
的更多信息。
注意到它是块级屏障也很重要。您无法使用__syncthreads()
同步不同的块。必须通过内核调用来同步块。
答案 1 :(得分:1)
你的问题是TEST_FLAG = 99。对于其中一个线程,它在线程0进入条件块之前执行,并为您提供未定义的行为。如果我注释掉TEST_FLAG = 99,代码将按预期运行。