OpenCL "跨平台" 编译 x64 / 32 位指针 GPU

4
我正在尝试优化我的内核函数,但遇到了一些问题。首先,这可能与Radeon R9(夏威夷)有关,但其他GPU设备也应该发生类似情况。
对于主机,我有两个平台选项。要么编译并作为x86程序运行,要么作为x64程序运行。根据我选择的平台不同,我会得到使用32位指针和指针算术或使用64位指针的不同编译内核。生成的IL代码显示了差异,在第一种情况下是
prog kernel &__OpenCL_execute_kernel(
  kernarg_u32 %_.global_offset_0,
  kernarg_u32 %_.global_offset_1,  
  ...

在第二种情况下,它是这样的:
prog kernel &__OpenCL_execute_kernel(
  kernarg_u64 %_.global_offset_0,
  kernarg_u64 %_.global_offset_1,  
  ...

在GPU上进行64位算术运算相当昂贵,需要消耗大量额外的VGPR。在我的情况下,64位指针版本需要8个额外的VGPR,并且有大约140个VALUInsts,如CodeXL所示。 性能总体上在我这种情况下慢了37%,在较慢的64位和较快的32位内核代码之间。除了内部指针算术之外,完全相同。我已经尝试过优化,但即使是普通的偏移量,我仍然被卡在很多ADD_U64 IL指令中,这些指令在ISA代码中产生两个指令:V_ADD_I32和V_ADDC_U32。当然,所有指针都需要双倍的私有内存空间(因此需要更多的VGPR)。
现在我的问题是:是否有一种方法可以“交叉”编译OpenCL内核,以便x64程序可以创建32位指针内核?我不需要在GPU中寻址那么多内存,因此寻址少于4 GiB的内存空间就可以了。由于我的主机也执行带有所有32个zmm寄存器的AVX-512指令,这只在x64模式下可用,因此x86程序不是一个选项。这使整个情况有点具有挑战性。

好吧,我的备用解决方案是生成一个x86子进程,使用共享内存并充当编译门。但是如果OpenCL中有一个简单的标志或(AMD特定的)设置可以解决问题,我宁愿不这样做。


请不要回复为什么会这样。我完全知道为什么x64程序和内核会表现出这种方式。

出于好奇,你使用什么作为支持AVX-512的主机CPU? - void_ptr
那是一款英特尔 Xeon Phi 7230(骑士着陆)处理器。 - Melissa P
OpenCL内核(在GPU内部)运行完全相同的代码,无论主机是64位还是32位。仅通过使用64位,您不会失去37%的性能。此外,数据类型对指针的大小非常清晰。您确定没有为缓冲区使用某些松散定义的数据类型吗?因此,在64位情况下使它们变得更大?只是猜测。 - DarkZeros
当主机为x64时,内核使用具有64位指针的平面内存指令(FLAT_LOAD_UBYTE)[请参见ISA指令手册第9章]。 当主机为x86时,内核使用缓冲内存指令(BUFFER_LOAD_UBYTE)。 您可以通过在“32位GPU构建”与“64位GPU构建”中进行CodeXL静态代码分析来检查差异。性能损失是由于需要更多VGPR,并减少了最大波数(从8个到6个)。 当然还有更多的ALU指令。 - Melissa P
1个回答

1

我有几个想法,但由于不熟悉AMD GPU OpenCL实现的内部机制,所以只能试探性地尝试。

  1. 你能否通过图像传递数据(即使它不是图像)?在英特尔GPU上,通过采样器提供了一条不同的路径,即使在64位版本中也可以避免64位算术。

  2. AMD是否有一个扩展允许您进行块读写?如果编译器证明地址是统一的(标量),这可能会有所帮助。例如:Intel Subgroups(启用某些块IO)。在英特尔的情况下,这有助于避免向总线发送一个SIMD的地址进行散布/收集(还可以节省寄存器空间)。

  3. (这有点牵强。)编译为OpenCL 1.2或更低版本是否有帮助?也就是说,指定-cl-std=CL1.2?如果编译器知道SVM未被使用(≥OpenCL 2.0)并且运行了对程序进行保守分析以证明它没有使用指针算术进行疯狂操作,那么它可能会使用32位算术,并隐式地向所有地址添加64位相对偏移量(使GPU程序认为它正在使用32位地址)。

再次声明,我对AMD的具体情况一无所知,但我能理解你遇到这个问题的痛苦。


感谢您的回复。
  1. 我使用图像而不是缓冲区进行了测试。这对性能产生了严重影响,我的内核时间从0.7000微秒增加到1.1000微秒。我必须研究一下,寄存器压力较小。也许这是解决方案的一部分。
  2. 我没有找到任何扩展或选项。
  3. 没有效果。任何其他编译器选项,无论是AMD特定的还是通用的,都没有任何效果。
我向AMD发起了支持请求,他们正在调查此问题。我现在正在使用编译器门控,生成一个执行OpenCL编译和处理的x86进程。目前它运行得相当不错。
- Melissa P

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接