C - 如何使用 GCC SSE 向量扩展访问向量的元素
Posted
技术标签:
【中文标题】C - 如何使用 GCC SSE 向量扩展访问向量的元素【英文标题】:C - How to access elements of vector using GCC SSE vector extension 【发布时间】:2009-11-20 17:12:16 【问题描述】:通常我使用以下类型处理 3D 矢量:
typedef vec3_t float[3];
使用 smth 初始化向量。喜欢:
vec3_t x_basis = 1.0, 0.0, 0.0;
vec3_t y_basis = 0.0, 1.0, 0.0;
vec3_t z_basis = 0.0, 0.0, 1.0;
并使用 smth 访问它们。喜欢:
x_basis[X] * y_basis[X] + ...
现在我需要一个使用 SSE 指令的向量算术。我有以下代码:
typedef float v4sf __attribute__ ((mode(V4SF)))
int main(void)
v4sf a,b,c;
a = (v4sf)0.1f,0.2f,0.3f,0.4f;
b = (v4sf)0.1f,0.2f,0.3f,0.4f;
c = (v4sf)0.1f,0.2f,0.3f,0.4f;
a = b + c;
printf("a=%f \n", a);
return 0;
GCC 支持这种方式。但... 首先,它给了我 0.00000 作为结果。其次,我无法访问此类向量的元素。 我的问题是:如何访问此类向量的元素?我需要smth。比如 a[0] 访问 X 元素, a[1] 访问 Y 元素等等。
PS:我使用以下代码编译此代码:
gcc -msse testgcc.c -o testgcc
【问题讨论】:
问题并不难,我不认为自己是 gcc 专家。下次使用更无害的标题时,我几乎跳过了这个问题。 【参考方案1】:安全且推荐的访问元素的方法是使用联合,而不是指针类型双关语,这会欺骗编译器的别名检测机制,并可能导致代码不稳定。
union Vec4
v4sf v;
float e[4];
;
Vec4 vec;
vec.v = (v4sf)0.1f,0.2f,0.3f,0.4f;
printf("%f %f %f %f\n", vec.e[0], vec.e[1], vec.e[2], vec.e[3]);
【讨论】:
不,elder_george 给出了一个更实际的例子——如果你在宏或内联中实现他的建议就足够安全了 我好像还不够清楚。使用指针进行类型双关是不好的,因为取消引用类型双关指针会破坏严格的别名规则。这会导致未定义的行为。通过内联或宏化并不会变得更安全。但是您可以使用编译器选项-fno-strict-aliasing,它正是为这样的损坏代码而设计的。生成的二进制文件可能会慢一些,因为您拒绝编译器进行优化。在 gcc.gnu.org/onlinedocs/gcc/... 的“-fstrict-aliasing”下阅读它以及为什么它不好。 是的,@drhirsh 是对的,对于@psihodelia 提供的示例,我的解决方案有效,但由于对齐损坏,在进行小的更改后它会失败。【参考方案2】:请注意 gcc 4.6 现在 supports 下标向量:
在 C 语言中,向量可以下标,就好像向量是具有相同元素数量和基本类型的数组一样。越界访问在运行时调用未定义的行为。可以使用 -Warray-bounds 启用向量订阅的越界访问警告。
【讨论】:
这仅适用于 C,不适用于 C++。有一个突出的错误:gcc.gnu.org/bugzilla/show_bug.cgi?id=51033【参考方案3】:您忘记了需要将a
重新解释为浮点数组。以下代码正常工作:
int main()
v4sf a,b,c;
a = (v4sf)0.1f,0.2f,0.3f,0.4f;
b = (v4sf)0.1f,0.2f,0.3f,0.4f;
c = (v4sf)0.1f,0.2f,0.3f,0.4f;
a = b + c;
float* pA = (float*) &a;
printf("a=[%f %f %f %f]\n",pA[0], pA[1], pA[2], pA[3]);
return 0;
P.S.:感谢这个问题,我不知道 gcc 有这样的 SSE 支持。
更新:一旦数组未对齐,此解决方案就会失败。 @drhirsh
提供的解决方案没有这个问题。
【讨论】:
以上是关于C - 如何使用 GCC SSE 向量扩展访问向量的元素的主要内容,如果未能解决你的问题,请参考以下文章