【问题标题】:How to access SIMD vector elements when overloading array access operators?重载数组访问运算符时如何访问 SIMD 向量元素?
【发布时间】:2014-12-20 16:47:16
【问题描述】:

我正在尝试使用 Xcode 6 上的 Clang 编译一些适用于 MSVC 的 SIMD 代码。不幸的是,我收到一个错误,其中数组访问运算符在我无法修复的自定义向量类中被重载。向量模板对使用 SIMD 内在函数的长度为 4 和 8 的数组进行了专门化,但是数组访问运算符返回对向量元素的引用(用于更新该元素)给我一个关于 clang 的错误“非常量引用不能绑定到向量元素”。

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]; }
                                      ^~~~~~

【问题讨论】:

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


    【解决方案1】:

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

    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;

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

    【讨论】:

    • 使用 simd 的全部原因是性能,所以不要做任何会大大减慢它的事情!
    • @olilarkin:当然——但如果你在性能关键循环中访问向量的单个元素,那么无论如何你都在做 SIMD 错误——通常这种操作应该只在循环,它不是性能关键。
    • 对不起,我误会了你......元素不是在性能关键部分单独访问,只是在初始化中
    • 酷——不过要小心严格的别名。考虑按照上面的建议将您的成员变量设为联合。
    • 相关:stackoverflow.com/q/24787268/@PaulR,你说得对,从技术上讲这违反了严格的别名要求。但实际上,每个现有的编译器(据我所知)都允许 SIMD 向量类型为其组件的数组起别名。因此,即使没有-fno-strict-aliasing,这实际上也是安全的
    【解决方案2】:

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

    • >= SSE4.1+:使用 PEXTRD 内部函数,例如 _mm_extract_ps
    • 在 SSE4.1 之前:_mm_cvtsi128_si32 + _mm_srli_si128 可访问任何 32 位项目(然后使用联合的情况)

    【讨论】:

      猜你喜欢
      • 2021-01-24
      • 1970-01-01
      • 2012-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-04
      • 1970-01-01
      相关资源
      最近更新 更多