CUDA动态并行和全局内存同步

时间:2013-11-02 10:26:26

标签: cuda

我无法弄清楚以下内容。

如果我在0调用之后启动内核并考虑例如块0中的线程__syncthreads(),那么所有其他块中的所有其他线程都会看到更改块0中的线程0对全局内存做了什么?

我的猜测是否定的。实际上,在CUDA C编程指南的synchronization functions部分中,声明:

  

void __syncthreads();   等待线程块中的所有线程都已到达此点,并且__syncthreads()之前的这些线程对块中的所有线程可见的所有全局和共享内存访问

但是,在谈论动态并行性中的global memory consistency时,CUDA C编程指南指出:

  

仅在第二次__syncthreads()调用之后,父网格的其他线程才能使用这些修改。

当涉及动态并行性时,__syncthreads()是否也可以跨块进行更改?

由于

1 个答案:

答案 0 :(得分:4)

__syncthreads()执行的唯一操作是您在CUDA C编程指南中描述的引用。除了在多个内核启动中划分内核执行的天真方法之外,CUDA中没有办法跨块进行同步,并且在性能方面存在所有缺点。因此,你自己猜到的第一个问题的答案是否定的。

在帖子的第二部分,您指的是CUDA C编程指南的一个具体示例,即

__global__ void child_launch(int *data) {
    data[threadIdx.x] = data[threadIdx.x]+1;
}

__global__ void parent_launch(int *data) { 
    data[threadIdx.x] = threadIdx.x;

    __syncthreads();

    if (threadIdx.x == 0) {
        child_launch<<< 1, 256 >>>(data);
        cudaDeviceSynchronize();
    }

    __syncthreads();
}

void host_launch(int *data) {
    parent_launch<<< 1, 256 >>>(data);
}

这里,256内核的所有parent_launch个线程都在data中写入内容。之后,线程0调用child_launch。需要第一个__syncthreads()来确保在子内核调用之前完成所有内存写入。在这一点上引用指南:

  

由于第一次__syncthreads()来电,孩子会看到data[0]=0data[1]=1,...,data[255]=255(没有__syncthreads()来电,孩子可以保证data[0]可以看到{。}}。

关于第二个__syncthreads(),指南解释了

  

当子网格返回时,线程0保证看到其子网格中的线程所做的修改。只有在第二次__syncthreads()调用之后,这些修改才可用于父网格的其他线程。

在该特定示例中,第二个__syncthreads()是冗余的,因为由于内核终止而存在隐式同步,但是在子内核启动之后必须执行其他操作时需要第二个__syncthreads()

最后,关于你在帖子中引用的句子:

  

仅在第二次__syncthreads()调用

之后,这些修改才可用于父网格的其他线程

请注意,在具体示例中,host_launch函数只启动了一个线程块。这可能有点误导了你。

在NVIDIA论坛上有一个有趣的讨论(可能甚至不止一个)关于跨块的线程同步

Synchronize all blocks in CUDA