5

我有一些手工矢量化的 C++ 代码,我正在尝试通过函数多版本化制作可分发的二进制文件。由于代码对不同的指令集(SSE2、AVX2、AVX512)使用 SIMD 内在函数,因此它使用模板特化来决定使用哪些内在函数。

整体架构大致如下:

template <unsigned W, unsigned N> struct SIMD {};  // SIMD abstraction

template <> struct SIMD<128, 8> {  // specialization for specific dimensions
  using Vec = __m128i;
  static always_inline Vec add(Vec a, Vec b) { return _mm_add_epi8(a, b); }
  ...  // many other SIMD methods
};

... // many other dimension specializations for different instruction sets

template <unsigned W, unsigned N> class Worker {
  void doComputation(int x) {
    using S = SIMD<W, N>;
    ... // do computations using S:: methods
  }
}

现在的问题是我需要不同的实例化Worker来具有不同的属性,因为每个实例化都会针对不同的指令集。像这样的东西:

template __attribute__((target("avx2")))     void Worker<256, 8>::doComputation(int x);
template __attribute__((target("avx512bw"))) void Worker<512, 8>::doComputation(int x);
...

以便为这些不同的目标编译这些不同的实例。但是,这仍然会在 Clang 上产生错误:

错误:always_inline 函数“添加”需要目标功能“avx2”,但是
       将被内联到编译的函数“doComputation”中
       不支持“avx2”

如果我用它来注释原始方法,__attribute__((target("avx2,avx512")))但如果没有 AVX-512 支持,它会在运行时执行非法硬件指令,所以我猜我使用上述带注释的专业化的直觉是行不通的。

有没有办法使用函数属性用 Clang 或 GCC 来表达这一点?

4

0 回答 0