在OpenCL中使用自己的Vector类型似乎更快

Using own Vector type in OpenCL seems to be faster

本文关键字:类型 Vector 自己的 OpenCL      更新时间:2023-10-16

我在OpenCL中看到了一个smallpt实现,作者在内核中使用了自己的向量类型和前置处理器宏函数。

typedef struct { float x, y, z; } Vec;
#define vinit(v, a, b, c) { (v).x = a; (v).y = b; (v).z = c; }
#define vsmul(v, a, b) { float k = (a); vinit(v, k * (b).x, k * (b).y, k * (b).z) }
#define vdot(a, b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z)
#define vnorm(v) { float l = 1.f / sqrt(vdot(v, v)); vsmul(v, l, v); }
and much more...

我测试了代码,并用标准的内置float3类型替换了用户定义的向量类型和操作。我很惊讶,作者最初的实现比内置float3的变体快10帧。在那之后,我用"英特尔OpenCL应用程序内核生成器"测试了一点情况,似乎可以确认内置函数的速度较慢。

有什么想法吗?供应商推荐内置向量类型:/

用户定义的向量是一个真正的3元素向量,使用3个浮点值。然而,OpenCL float3矢量实际上使用的是float4矢量,如cl_platform.h:所示

/* cl_float3 is identical in size, alignment and behavior to cl_float4. See section 6.1.5. */
typedef  cl_float4  cl_float3;

最初使用矢量是OpenCL的推荐编程技术。由于与普通的非矢量代码相比,采用了完整的SIMD架构。

但是随着OpenCL编译器的发展,现在该编译器足够聪明,可以在内部对用户代码进行矢量化有时(我也在其他内核中看到过,甚至在我自己的内核中也看到过)最好用纯元素编写代码,并让编译器重新向量化,而不是使用默认的向量类型因此,我建议除非vector简化了编程任务并且更易于阅读(例如2D处理等),否则现在不要使用OpenCL vector。

用户定义的vector3可能使用的寄存器更少,溢出也更少。或者,另一种矢量排列对算法更好,编译器可以在用户定义的矢量情况下自由地重新塑造代码。

应该使用编译的PTX代码对正在发生的事情进行独立分析。

添加一点。对于NVIDIA GPU(我不知道AMD),有32位(LD.32)、64位(LD.64)和128位(LD.128)的加载指令,但没有96位加载。从DRAM加载一个真正的float3被实现为两个独立的指令——一个LD.32和一个LD.64。如果像对待float2、double或float4那样,在warp中的连续线程中加载连续的float3,那么实际上是在两个独立的指令中以96位的步长访问数据,从而导致回放。存储说明也是如此。我想这就是选择将它们类型定义为float4的原因。

相关文章: