OpenCL“交叉” – 编译x64 / 32位指针GPU

我正在尝试优化我的内核函数并遇到一些问题.首先,这可能与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位指针内核?我不需要在GPU中处理那么多内存,因此寻址小于4 GiB的内存空间是可以的.由于我的主机也在执行带有所有32个zmm寄存器的AVX-512指令,这些寄存器仅在x64模式下可用,因此不能选择x86程序.这使得整个局势有点挑战.

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

请不要回复为什么回复.我完全清楚为什么x64程序和内核的行为方式如此.

最佳答案 我有几个想法,但不熟悉AMD GPU OpenCL实现的内容,我在黑暗中刺伤.

>你能通过图像传递数据(即使不是)?在通过采样器的英特尔GPU上提供了不同的路径,即使在64位版本中也可以避免64位算术.
> AMD是否有一个允许您阻止读写的扩展名?如果编译器证明地址是统一的(标量),这可能会有所帮助.例如.像Intel Subgroups这样的东西(它可以启用一些块IO).在英特尔,这有助于避免在总线上传输SIMD的地址,以进行分散/收集(并节省寄存器空间).
>(这是一个延伸.)为OpenCL 1.2或更低版本编译是否有帮助?也就是说,指定-cl-std = CL1.2?如果编译器知道没有使用SVM(> = OpenCL 2.0)并且对程序运行保守分析以证明它没有用指针算法做一些疯狂的事情,那么它可以在32位和隐式地进行算术运算.为所有地址添加64位相对偏移量(使GPU程序认为它使用的是32位地址).

我再一次对AMD的细节一无所知,但我对这个问题感到痛苦.

点赞