OpenCL"交叉" - 编译x64 / 32位指针GPU

时间:2016-07-12 16:29:22

标签: opencl cross-compiling

我试图优化我的内核功能并遇到一些问题。首先,这可能与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所示。在我的情况下,在较慢的64位和较快的32位内核代码之间,整体性能大约低37%。除了内部指针算术之外,它完全相同。我试图对此进行优化,但即使使用普通偏移量,我仍然会遇到大量ADD_U64 IL指令,这些指令在ISA代码中产生两条指令:V_ADD_I32和V_ADDC_U32。当然,所有指针都需要双重私有内存空间(因此需要更多VGPR)。

现在我的问题是:是否可以通过"交叉" - 编译OpenCL内核,以便x64程序可以创建32位指针内核?我不知道#39;需要在GPU中处理那么多内存,因此寻址小于4 GiB的内存空间是可以的。由于我的主机也在执行带有所有32个zmm寄存器的AVX-512指令,这些寄存器仅在x64模式下可用,因此不能选择x86程序。这使得整个局势有点挑战。

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

请不要回答为什么回复。我完全清楚为什么x64程序和内核会以这种方式运行。

1 个答案:

答案 0 :(得分: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中进行算术运算。 -bit并隐式地为所有地址添加64位相对偏移量(使GPU程序认为它使用的是32位地址)。

  4. 同样,我对AMD的细节一无所知,但我对这个问题感到痛苦。