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 向量扩展访问向量的元素的主要内容,如果未能解决你的问题,请参考以下文章

使用 GCC 向量扩展存储、修改和检索字符串?

使用 SSE 缩放复杂向量

GCC 向量扩展的内存对齐问题

SSE2 向量移位

使用带有 STL 向量的 SSE 计算平均值

xmmintrin.h 与 gcc 向量扩展