我有一些手工矢量化的 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 来表达这一点?