如何在重载数组访问运算符时访问SIMD向量元素?

时间:2014-10-24 19:19:48

标签: c++ operator-overloading clang simd avx

我正在尝试制作一些适用于MSVC的SIMD代码与Xcode 6上的Clang一起编译。不幸的是,我得到一个错误,其中数组访问运算符已经在我无法修复的自定义向量类中重载。向量模板具有使用SIMD内在函数的长度为4和8的数组的特化,但是数组访问运算符返回对向量元素的引用(用于更新该元素)在clang上给出了错误"非const引用不能绑定到vector元素"。

Full source code

重载运算符:

#ifdef _MSC_VER
  float operator[](int idx) const { return v.m256_f32[idx]; } // m256_f32 MSVC only
  float& operator[](int idx) { return v.m256_f32[idx]; }
#else
  float operator[](int idx) const { return v[idx]; }
  float& operator[](int idx) { return v[idx]; }
#endif

来自Clang的错误:

non-const reference cannot bind to vector element
  float& operator[](int idx) { return v[idx]; }
                                      ^~~~~~

2 个答案:

答案 0 :(得分:5)

我认为您可能需要使用联盟,例如:

union U {
    __m256 v;
    float a[8];
};

然后值运算符为:

float operator[](int idx) const { U u = { v }; return u.a[idx]; }

参考运算符虽然比较棘手,但我能看到的唯一方法是通过类型惩罚,所以通常需要注意:

float& operator[](int idx) { return ((float *)&v)[idx]; }

我甚至不确定这会编译,您可能需要-fno-strict-aliasing

为避免这种肮脏,我想您可以考虑将成员变量从__m256 v;更改为U u;

我希望你不要在任何性能关键的循环中做这种事情。

答案 1 :(得分:2)

这仅适用于阅读,因此您无法返回对float的引用。但这应该适用于运行时值:

  • > = SSE4.1 +:使用像_mm_extract_ps这样的PEXTRD内在函数
  • 在SSE4.1:_mm_cvtsi128_si32 + _mm_srli_si128之前访问任何32位项目(然后是工会案例)