我有一个关于 CUDA 同步的问题。特别是,我需要对 if 语句中的同步进行一些说明。我的意思是,如果我将 __syncthreads() 放在块内的一小部分线程命中的 if 语句的范围内,会发生什么?我认为一些线程将保持“永远”等待其他不会达到同步点的线程。所以,我编写并执行了一些示例代码来检查:
__global__ void kernel(float* vett, int n)
{
int index = blockIdx.x*blockDim.x + threadIdx.x;
int gridSize = blockDim.x*gridDim.x;
while( index < n )
{
vett[index] = 2;
if(threadIdx.x < 10)
{
vett[index] = 100;
__syncthreads();
}
__syncthreads();
index += gridSize;
}
}
令人惊讶的是,我观察到输出非常“正常”(64 个元素,块大小 32):
100 100 100 100 100 100 100 100 100 100 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
100 100 100 100 100 100 100 100 100 100 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
所以我通过以下方式稍微修改了我的代码:
__global__ void kernel(float* vett, int n)
{
int index = blockIdx.x*blockDim.x + threadIdx.x;
int gridSize = blockDim.x*gridDim.x;
while( index < n )
{
vett[index] = 2;
if(threadIdx.x < 10)
{
vett[index] = 100;
__syncthreads();
}
__syncthreads();
vett[index] = 3;
__syncthreads();
index += gridSize;
}
}
输出是:
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
再一次,我错了:我认为 if 语句中的线程在修改了向量的元素后,会保持等待状态,永远不会超出 if 范围。所以...你能澄清一下发生了什么吗?在同步点之后获取的线程是否会解除阻塞在屏障处等待的线程?如果您需要重现我的情况,我使用了带有 SDK 4.2 的 CUDA Toolkit 5.0 RC。提前非常感谢。