Cuda 是否同步网格中的所有线程?
…还是仅当前扭曲或块中的线程 另外,当特定块中的线程(在内核中)遇到以下行Cuda 是否同步网格中的所有线程?,cuda,Cuda,…还是仅当前扭曲或块中的线程 另外,当特定块中的线程(在内核中)遇到以下行 __shared__ float srdMem[128]; 他们会只声明这个空间一次吗(每个块) 它们显然都是异步运行的,因此如果块22中的线程23是第一个到达此行的线程,而块22中的线程69是最后一个到达此行的线程,那么线程69将知道它已经被声明了?\u syncthreads()等待,直到同一块中的所有线程都已到达该命令,并且扭曲中的所有线程都已到达该语句-这意味着属于threadblock的所有扭曲都必须到达该
__shared__ float srdMem[128];
他们会只声明这个空间一次吗(每个块)
它们显然都是异步运行的,因此如果块22中的线程23是第一个到达此行的线程,而块22中的线程69是最后一个到达此行的线程,那么线程69将知道它已经被声明了?\u syncthreads()
等待,直到同一块中的所有线程都已到达该命令,并且扭曲中的所有线程都已到达该语句-这意味着属于threadblock的所有扭曲都必须到达该语句
如果在内核中声明共享内存,则该数组将仅对一个线程块可见。因此,每个块都有自己的共享内存块。syncthreads()命令是块级的同步屏障。这意味着,当一个区块中的所有螺纹都达到屏障时,可以安全使用。也可以在条件代码中使用\u syncthreads()
,但只有当所有线程对此类代码求值相同时,否则执行可能会挂起或产生意外的副作用
使用\uuu syncthreads()
的示例:()
要同步网格中的所有线程,当前存在而不是本机API调用。在网格级别同步线程的一种方法是使用连续的内核调用,因为此时所有线程都从同一点结束并重新开始。它通常也称为CPU同步或隐式同步。因此,它们都是同步的
使用此技术()的示例:
关于第二个问题是,它会声明每个块指定的共享内存量。考虑到可用共享内存的数量是按SM测量的。因此,我们应该非常小心如何将共享内存与启动配置一起使用我同意这里的所有答案,但我认为我们在这里遗漏了一个重要的点w.r.t第一个问题。我不回答第二个答案,因为上面的答案回答得很好 GPU上的执行以扭曲为单位。warp是一组32个线程,特定warp的每个线程在同一时间执行相同的指令。如果在一个块中分配128个线程,那么GPU将有(128/32=)4个扭曲 现在问题变成了“如果所有线程都在执行相同的指令,那么为什么需要同步?”。答案是我们需要同步属于同一块的扭曲__syncthreads不会同步扭曲中的线程,它们已同步。它同步属于同一块的扭曲 这就是为什么您的问题的答案是:uu syncthreads不会同步网格中的所有线程,而是属于一个块的线程,因为每个块都独立执行
如果您想同步一个网格,那么将内核(K)分成两个内核(K1和K2),并调用这两个内核。它们将被同步(K1完成后将执行K2)。现有的答案在回答
\uu syncthreads()
如何工作方面做得很好(它允许块内同步),我只想添加一个更新,即现在有更新的块间同步方法。自CUDA 9.0以来,引入了“协作组”,允许同步整个块网格(如中所述)。这实现了与启动新内核(如上所述)相同的功能,但通常可以以较低的开销实现,并使代码更具可读性。为了提供更多详细信息,除了答案外,还引用:
更一般地说,_syncthreads()是一种屏障原语,旨在保护您免受块内的读后写内存争用情况的影响
使用规则非常简单:
共享内存分别分配给每个块,但不是同时分配。当SM实际开始执行该块时,共享内存在那个时候被分配。这实际上不是真的。
shared
数组被分配给设备中的每个块。@KiaMorot:我想你误解了什么。没有什么可抱怨的
__global__ void globFunction(int *arr, int N)
{
__shared__ int local_array[THREADS_PER_BLOCK]; //local block memory cache
int idx = blockIdx.x* blockDim.x+ threadIdx.x;
//...calculate results
local_array[threadIdx.x] = results;
//synchronize the local threads writing to the local memory cache
__syncthreads();
// read the results of another thread in the current thread
int val = local_array[(threadIdx.x + 1) % THREADS_PER_BLOCK];
//write back the value to global memory
arr[idx] = val;
}