gpt4 book ai didi

multithreading - 我们可以使用 `shuffle()` 指令在 WaveFront 中的项目(线程)之间进行 reg-to-reg 数据交换吗?

转载 作者:行者123 更新时间:2023-12-02 02:31:35 30 4
gpt4 key购买 nike

众所周知,WaveFront (AMD OpenCL) 与 WARP (CUDA) 非常相似:http://research.cs.wisc.edu/multifacet/papers/isca14-channels.pdf

GPGPU languages, like OpenCL™ and CUDA, are called SIMT because they map the programmer’s view of a thread to a SIMD lane. Threads executing on the same SIMD unit in lockstep are called a wavefront (warp in CUDA).

众所周知,AMD 建议我们使用本地内存(减少)数字加法。为了加速加法(Reduce),建议使用向量类型:http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/01/AMD_OpenCL_Tutorial_SAAHPC2010.pdf

enter image description here

<小时/>

但是WaveFront中的项目(线程)之间是否存在任何优化的寄存器到寄存器数据交换指令:

例如,此洗牌指令可以执行来自 8 个线程/ channel 的 8 个元素的 Reduce(将数字相加),3 个周期,无需任何同步,也无需使用任何缓存/本地/共享内存(每次访问有大约 3 个周期的延迟)。

即线程将其值直接发送到其他线程的寄存器:https://devblogs.nvidia.com/parallelforall/faster-parallel-reductions-kepler/

enter image description here

或者在 OpenCL 中我们只能使用指令 gentypen shuffle( gentypem x, ugentypen mask )只能用于矢量类型,例如 float16/uint16进入每个项目(线程),但不在 WaveFront 中的项目(线程)之间:https://www.khronos.org/registry/OpenCL/sdk/1.1/docs/man/xhtml/shuffle.html

我们可以使用类似 shuffle() 的东西吗?对于 WaveFront 中的项目(线程)之间的寄存器到寄存器数据交换,哪个比通过本地内存进行数据交换更快?

<小时/>

AMD OpenCL 中是否有用于 WaveFront 内寄存器到寄存器数据交换的指令,例如指令 __any() , __all() , __ballot() , __shfl()对于 WARP 内(CUDA):http://on-demand.gputechconf.com/gtc/2015/presentation/S5151-Elmar-Westphal.pdf

扭曲投票功能:

  • __any(predicate)如果任何谓词为扭曲中的线程返回非零
  • __all(predicate)如果所有谓词都返回非零扭曲中的线程返回非零
  • __ballot(predicate)返回包含各个位的位掩码谓词返回非零的线程集
  • __shfl(value, thread)从请求的线程返回值(但前提是该线程还执行了 __shfl() 操作)
<小时/>

结论:

众所周知,在 OpenCL-2.0 中,有一些具有类似于 WaveFronts 的 SIMD 执行模型的子组:Does the official OpenCL 2.2 standard support the WaveFront?

对于子组,有 - 第 160 页:http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_OpenCL_Programming_User_Guide2.pdf

  • int sub_group_all(int predicate)与 CUDA- __all(predicate) 相同
  • int sub_group_any(int predicate);与 CUDA- __any(predicate) 相同

但是在 OpenCL 中没有类似的函数:

  • CUDA-__ballot(predicate)
  • CUDA-__shfl(value, thread)

2016 年 8 月 28 日发布的第 4 版 OpenCL 扩展最终草案 #35 中仅包含 Intel 指定的内置 shuffle 函数:intel_sub_group_shuffle , intel_sub_group_shuffle_down , intel_sub_group_shuffle_down , intel_sub_group_shuffle_up : https://www.khronos.org/registry/OpenCL/extensions/intel/cl_intel_subgroups.txt

OpenCL中也有一些函数,通常通过shuffle-functions实现,但并不是所有的函数都可以使用shuffle-functions实现:

  • <gentype> sub_group_broadcast( <gentype> x, uint sub_group_local_id );
  • <gentype> sub_group_reduce_<op>( <gentype> x );
  • <gentype> sub_group_scan_exclusive_<op>( <gentype> x );
  • <gentype> sub_group_scan_inclusive_<op>( <gentype> x );

摘要:

  1. shuffle - 函数保持更灵活的函数,并通过直接寄存器到寄存器数据交换确保线程之间尽可能最快的通信。

  2. 但功能 sub_group_broadcast/_reduce/_scan不保证寄存器之间的直接数据交换,并且这些子组功能不太灵活。

最佳答案

gentype work_group_reduce<op> ( gentype  x)

对于版本>=2.0

但它的定义没有提及任何有关使用本地内存或寄存器的内容。这只是将每个协作者的 x 值减少为所有值的总和。此功能必须被所有工作组项目命中,因此它不采用波前级别方法。另外,浮点运算的顺序也无法保证。

也许有些供应商采用注册方式,而有些供应商则使用本地内存。我猜Nvidia是用寄存器来做的。但旧的主流 AMD GPU 的本地内存带宽为 3.7 TB/s,这仍然是一个不错的数字。 (编辑:不是 22 TB/s)对于 2k 核心,这意味着每个核心每个周期接近 1.5 个字节,或者每个缓存线更快。

对于%100寄存器(如果不溢出到全局内存)版本,如果元素数量只有8或16,您可以减少线程数量并在线程本身中进行矢量化减少,而无需与其他人通信。例如

v.s0123 += v.s4567
v.s01 += v.s23
v.s0 += v.s1

它应该类似于 __m128i _mm_shuffle_epi8 及其在 CPU 上编译时的总和版本,并且非标量实现将在 GPU 上使用相同的 SIMD 来执行这 3 个操作。

此外,使用这些向量类型往往会使用高效的内存事务,甚至对于全局和本地事务也是如此,而不仅仅是寄存器。

SIMD 一次仅适用于单个波前,但一个波前可能由多个 SIMD 处理,因此,此矢量运算并不意味着正在使用整个波前。或者甚至整个波前可能正在计算一个周期中所有向量的第一个元素。但对于 CPU 来说,最合理的选择是 SIMD 逐一计算工作项(avx、sse),而不是通过相同的索引元素并行计算它们。

<小时/>

如果主工作组不符合要求,则会生成子内核并使用动态宽度内核来进行此类操作。子内核同时在另一个称为sub-group的组上工作。这是在设备端队列中完成的,并且需要 OpenCl 版本至少为 2.0。

http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_OpenCL_Programming_User_Guide2.pdf 中查找“设备端排队”

AMD APP SDK 支持子组

关于multithreading - 我们可以使用 `shuffle()` 指令在 WaveFront 中的项目(线程)之间进行 reg-to-reg 数据交换吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42260986/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com