Concurrency 是否可以保证WaveFront(OpenCL)中的所有线程始终同步?

Concurrency 是否可以保证WaveFront(OpenCL)中的所有线程始终同步?,concurrency,opencl,gpgpu,amd,simd,Concurrency,Opencl,Gpgpu,Amd,Simd,众所周知,有扭曲(在CUDA中)和波前(在OpenCL中): CUDA中的扭曲: 4.1。SIMT体系结构 扭曲一次执行一条公共指令,因此效率最高 当一个扭曲的所有32个线程都同意执行时实现 路径如果扭曲的线程通过依赖于数据的条件 分支时,扭曲会连续执行每个分支路径,禁用 不在该路径上的线程,并且当所有路径完成时 线程会聚回相同的执行路径。分支发散 仅在扭曲内发生不同的扭曲独立执行 不管它们是执行公共代码还是不相交代码 路径 SIMT体系结构类似于SIMD(单指令、多指令) 数据)单个指

众所周知,有扭曲(在CUDA中)和波前(在OpenCL中):

  • CUDA中的扭曲
4.1。SIMT体系结构

扭曲一次执行一条公共指令,因此效率最高 当一个扭曲的所有32个线程都同意执行时实现 路径如果扭曲的线程通过依赖于数据的条件 分支时,扭曲会连续执行每个分支路径,禁用 不在该路径上的线程,并且当所有路径完成时 线程会聚回相同的执行路径。分支发散 仅在扭曲内发生不同的扭曲独立执行 不管它们是执行公共代码还是不相交代码 路径

SIMT体系结构类似于SIMD(单指令、多指令) 数据)单个指令控制的向量组织 多个处理元素。关键区别在于SIMD向量 组织向软件公开SIMD宽度,而SIMT 指令指定单个进程的执行和分支行为 线

  • OpenCL中的波前
在运行期间,第一个波前被发送到计算单元以 运行,然后第二个波前被发送到计算单元,依此类推。 一个波前内的功项并行执行并锁定 步骤。但是不同的波前是按顺序执行的


即我们知道:

  • WARP(CUDA)中的线程是SIMT线程,每次总是执行相同的指令,并且总是保持同步,即WARP的线程与(CPU上的)相同

  • 波阵面(OpenCL)中的线程是始终并行执行的线程,但不一定所有线程都执行完全相同的指令,也不一定所有线程都同步

但是,是否有任何保证可以保证波前中的所有线程始终同步,例如WARP中的线程或SIMD中的通道


结论

  • 波阵面线程(项目)始终同步-锁定步骤:“波阵面在锁定步骤中相对于彼此执行多个工作项目。”
  • 映射到SIMD块上的波前:“波前中的所有工作项都指向流量控制的两条路径”
  • 映射到SIMD通道的每个波前线程(项目)
  • 第20页:

    第1章OpenCL体系结构和AMD加速并行处理

    1.1术语

    波前和工作组是与计算有关的两个概念 提供数据并行粒度的内核。A波前 执行锁定步骤中与每个步骤相关的多个工作项 其他的16个工作项在向量上并行执行 单位,整个波前覆盖四个时钟周期。信息技术 是流量控制可能影响的最低级别。这意味着如果 波前内的两个工作项通过不同的流动路径 控制,波阵面中的所有工作项都流向两条流动路径 控件

    以下情况也是如此:

    • (第45页)第2章GCN设备的OpenCL性能和优化
    • (第81页)第3章常青和北方岛屿设备的OpenCL性能和优化

    首先,您可以查询一些值:

    CL_DEVICE_WAVEFRONT_WIDTH_AMD
    CL_DEVICE_SIMD_WIDTH_AMD
    CL_DEVICE_WARP_SIZE_NV
    CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE
    
    但据我所知,只有东道主一方

    假设这些查询返回了
    64
    ,您的问题重视线程的隐式同步

    如果有人选择本地范围=4怎么办

    由于opencl从开发人员那里提取了硬件时钟,所以在运行时,您无法从内核执行中知道实际的SIMD或波前大小

    例如,AMD NCU有64个着色器,但在同一计算单元内有16个宽SIMD、8个宽SIMD、4个宽SIMD、2个宽SIMD,甚至两个标量单元

    4个本地线程可以在两个标量和一个2宽单元或任何其他SIMD组合上共享。内核代码不可能知道这一点。即使它知道某种计算方法,您也无法知道在运行时在随机计算单元(64个着色器)中的下一个内核执行(甚至下一个工作组)将使用哪个SIMD组合。

    或者,GCN CU(其中包含4x16个SIMD)可以为每个SIMD分配1个线程,使所有4个线程完全独立。如果它们都在同一个SIMD中,那么你就幸运了。无法保证知道“在”内核执行之前。即使在您知道之后,下一个内核可能会有所不同,因为无法保证选择相同的SIMD分配(后台内核、3d可视化软件,甚至操作系统都可能在管道中放置气泡)

    无法保证在内核执行之前命令/提示/查询N个线程以相同的SIMD或相同的WARP运行。然后在内核中,没有像get_global_id(0)那样的命令来获取线程的波前索引。然后在内核之后,您不能依赖数组结果,因为下一次内核执行可能不会对完全相同的项使用相同的SIMD。即使是来自其他波前的一些项目也可以与来自当前波前的项目交换,只是为了通过驱动程序或硬件进行优化(nvidia最近推出了负载均衡器,并且可能正在这样做,amd的NCU将来也可能会使用类似的东西)

    即使您在硬件和驱动程序上猜测SIMD上线程的正确组合,在另一台计算机上也可能完全不同


    如果从性能角度考虑,您可以尝试: