Parallel processing CUDA\uuuuSyncThreads()在扭曲中的用法

Parallel processing CUDA\uuuuSyncThreads()在扭曲中的用法,parallel-processing,cuda,synchronization,Parallel Processing,Cuda,Synchronization,如果一个块中的所有线程都必须在代码中的同一点上,那么如果要启动的线程数等于扭曲中的线程数,我们是否需要u syncthreads函数 注意:没有额外的线程或块,内核只有一个扭曲 示例代码: shared _voltatile_ sdata[16]; int index = some_number_between_0_and_15; sdata[tid] = some_number; output[tid] = x ^ y ^ z ^ sdata[index]; 即使正在并行执行扭曲,您仍然需

如果一个块中的所有线程都必须在代码中的同一点上,那么如果要启动的线程数等于扭曲中的线程数,我们是否需要u syncthreads函数

注意:没有额外的线程或块,内核只有一个扭曲

示例代码:

shared _voltatile_ sdata[16];

int index = some_number_between_0_and_15;
sdata[tid] = some_number;
output[tid] = x ^ y ^ z ^ sdata[index];

即使正在并行执行扭曲,您仍然需要
\uu syncthreads()
。硬件中的实际执行可能不是并行的,因为SM(流多处理器)中的核数可能少于32。例如,GT200体系结构在每个SM中有8个内核,因此您永远无法确保代码中的所有线程都位于同一点。

更新了有关使用volatile的更多信息

假设您希望所有线程处于同一点,因为它们正在将其他线程写入的数据读取到共享内存中,如果您正在启动单个扭曲(在每个块中),则您知道所有线程都在一起执行。从表面上看,这意味着您可以省略
\uu syncthreads()
,这是一种称为“扭曲同步编程”的实践。然而,有一些事情需要注意

  • 请记住,如果线程内语义保持正确,编译器将假定它可以进行优化,包括延迟存储到内存,在内存中数据可以保存在寄存器中<代码>\uuu syncthreads()充当了一个障碍,因此确保在其他线程读取数据之前将数据写入共享内存。使用
    volatile
    会导致编译器执行内存写入,而不是保留在寄存器中,但是这有一些风险,更像是一种黑客行为(这意味着我不知道将来会受到什么影响)
    • 从技术上讲,您应该始终使用
      \uu syncthreads()
      来符合CUDA编程模型
  • 扭曲大小一直是32,但您可以:
    • 在编译时,在设备代码中使用特殊变量
      warpSize
      (记录在4.1版本B.4节“内置变量”下)
    • 在运行时使用cudaDeviceProp结构的warpSize字段(记录在中)

请注意,一些SDK示例(特别是Reduce和scan)使用了这种扭曲同步技术。

\u syncthreads()在某些密集型代码(例如Reduce和scan)中可能会对性能产生影响。如果希望在线程之间共享数据(例如,通过共享内存),则会出现此问题。在这些情况下,如果在加载之后有一个存储,则您知道整个warp将在任何线程开始加载之前执行存储,即使LS单元的数量(CUDA内核的数量与此无关)小于warp大小。关于编译器优化还有其他一些注意事项-1:CUDA型号保证一个warp中的所有线程都是同步的。引用《编程指南》:由于warp一次执行一条公共指令,因此warp中的线程是隐式同步的,这有时可以用来省略_syncthreads()为了获得更好的性能。较新的Kepler_Tuning_Guide.pdf的第1.4.8节通过取消_syncthreads(),降低了利用扭曲同步编程的价值。当您说“如果底层内核数小于扭曲大小,则适用此方法”时,这是否意味着C1060是不可能的?另外,如果我在内核中只启动16个线程呢?C1060仍然可以。您真正关心的是对某个位置的写入,然后是读取(或WAR/WAW),您知道整个扭曲将在扭曲中的任何线程开始后续读取之前完成写入。如果您启动的线程少于32个,同样的行为也适用,它仍然只是一个单一的扭曲,尽管效率更低。请注意,我强烈建议您考虑启动更大的块,每个块只有一个翘曲,您将发现不可能覆盖大多数延迟。我添加了一个类似的代码。线程将读取前一行代码中写入的数据。因为共享数据也有一些按位操作,所以我可以将按位操作分离出来,并将它们放在读取之前吗?warp中的所有线程是否仍在执行相同的代码行?我认为这在很大程度上是一个无关紧要的问题,因为如果每个块运行
warpSize
(32)个线程,那么最终的性能可能会低于在CPU上运行算法的性能。@RogerDahl我不确定我是否完全理解,你是说仅仅在warp中使用32个线程总是比任何内核的CPU都慢?我没有说“总是”,因为可能会出现一组特殊的情况,而我的声明不适用于这些情况。问题是,如果将每个块的
线程数限制为
warpSize
,则很可能会导致占用率极低(受每个多处理器的
最大块数限制),这将导致性能低下。此外,如果您可以简单地增加每个块的
线程数
并添加
\uu syncthreads()
以获得更好的性能,那么人为地将每个块的
线程数保持在较低的水平是没有意义的。因此,正如您所看到的,对于一个限制为16个线程的算法,您所能做的任何优化都将是徒劳的。在CPU上运行会更好。呵呵。因此,他告诉我避免在评论中进行长时间的讨论,并希望我将此移到聊天中。因此,如果您在阅读本文后仍然有问题,请继续并打开一个新问题。引用自:但是,由于CBC模式需要前一步的密文来处理下一步,因此在前一个块被加密之前,无法开始加密该块。因此,我们不能指望在这种模式的加密阶段进行并行处理。