CUDA动态并行与全局内存同步
我想不出以下几点CUDA动态并行与全局内存同步,cuda,Cuda,我想不出以下几点 如果我启动一个内核,例如在代码< >代码> 0 中考虑线程 0代码/代码>,在代码< > ySythththRead()>代码>调用之后,所有其他块中的所有其他线程都会看到在代码< > 0 < /COD> < /P>中,线程 0 < /代码>对全局内存所做的更改吗? 我的猜测是否定的。事实上,在《CUDA C编程指南》的一节中,它指出: void\uuuu syncthreads() 等待线程块中的所有线程都达到此点,并且块中的所有线程都可以看到这些线程在\uu syncthr
如果我启动一个内核,例如在代码< >代码> 0 <代码>中考虑线程<代码> 0代码/代码>,在代码< > ySythththRead()>代码>调用之后,所有其他块中的所有其他线程都会看到在代码< > 0 < /COD> < /P>中,线程<代码> 0 < /代码>对全局内存所做的更改吗? 我的猜测是否定的。事实上,在《CUDA C编程指南》的一节中,它指出:
void\uuuu syncthreads()代码>
等待线程块中的所有线程都达到此点,并且块中的所有线程都可以看到这些线程在\uu syncthreads()
之前进行的所有全局和共享内存访问
但是,在谈到动态并行时,《CUDA C编程指南》指出:
只有在第二次调用\uuu syncthreads()
后,这些修改才会对父网格的其他线程可用
当涉及到动态并行性时,\uuu syncthreads()
是否也可以跨块进行更改
谢谢由\uu syncthreads()
执行的唯一操作是您自己在CUDA C编程指南中引用的操作。在CUDA中,除了将一个内核的执行划分为多个内核启动的幼稚方法之外,没有任何方法可以跨块同步,但在性能方面存在所有缺点。因此,你的第一个问题的答案,正如你自己猜测的,是否定的
在文章的第二部分中,您提到了CUDAC编程指南的一个具体示例,即
__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);
}
\uuuuu全局\uuuuu无效子项\u启动(int*数据){
数据[threadIdx.x]=数据[threadIdx.x]+1;
}
__全局\uuuuuu无效父\u启动(int*数据){
数据[threadIdx.x]=threadIdx.x;
__同步线程();
if(threadIdx.x==0){
儿童启动>(数据);
cudaDeviceSynchronize();
}
__同步线程();
}
无效主机启动(int*数据){
母公司发布>(数据);
}
在这里,parent\u-launch
内核的所有256
线程都在数据中写入内容。之后,线程0
调用child\u launch
。需要第一个\uuu syncthreads()
,以确保在子内核调用之前完成所有内存写入。引用关于这一点的指南:
由于第一个\u syncthreads()
调用,子级将看到数据[0]=0
,数据[1]=1
,…,数据[255]=255
(如果没有\u syncthreads()
调用,子级将保证只看到数据[0]
)
关于第二个\uuu syncthreads()
,本指南解释如下:
当子网格返回时,线程0
保证看到子网格中的线程所做的修改。只有在第二次调用\uuu syncthreads()
后,这些修改才会对父网格的其他线程可用
在该特定示例中,第二个\uuuuu syncthreads()
是冗余的,因为内核终止会导致隐式同步,但在子内核启动后必须执行其他操作时,则需要第二个\uuu syncthreads()
最后,关于你在帖子中引用的句子:
只有在第二次调用\uuu syncthreads()
后,这些修改才会对父网格的其他线程可用
请注意,在特定示例中,host\u launch
函数只启动了一个线程块。这也许有点误导了你
在英伟达论坛上,有一个有趣的讨论(可能不止一次),该论坛的标题是“”的线程同步。
由\uuu syncthreads()
执行的唯一操作是您自己在CUDA C编程指南中引用的操作。在CUDA中,除了将一个内核的执行划分为多个内核启动的幼稚方法之外,没有任何方法可以跨块同步,但在性能方面存在所有缺点。因此,你的第一个问题的答案,正如你自己猜测的,是否定的
在文章的第二部分中,您提到了CUDAC编程指南的一个具体示例,即
__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);
}
\uuuuu全局\uuuuu无效子项\u启动(int*数据){
数据[threadIdx.x]=数据[threadIdx.x]+1;
}
__全局\uuuuuu无效父\u启动(int*数据){
数据[threadIdx.x]=threadIdx.x;
__同步线程();
if(threadIdx.x==0){
儿童启动>(数据);
cudaDeviceSynchronize();
}
__同步线程();
}
无效主机启动(int*数据){
母公司发布>(数据);
}
在这里,parent\u-launch
内核的所有256
线程都在数据中写入内容。之后,线程0
调用child\u launch
。需要第一个\uuu syncthreads()
,以确保在子内核调用之前完成所有内存写入。引用关于这一点的指南:
由于第一个\u syncthreads()
调用,子级将看到数据[0]=0
,数据[1]=1
,…,数据[255]=255
(如果没有\u syncthreads()
调用,子级将保证只看到数据[0]
)
关于第二个\uuu syncthreads()
,本指南解释如下:
当子网格返回时,线程0
保证看到子网格中的线程所做的修改。只有在第二次调用\uuu syncthreads()
后,这些修改才会对父网格的其他线程可用
在该特定示例中,第二个\uuuu syncthreads()
是冗余的,因为由于内核终止而存在隐式同步,但是第二个\uuu syncthreads()
变为nee