禁用非Haswell处理器上的AVX2功能

Ale*_*ros 2 c++ sse avx2

我已经写了一些AVX2代码在Haswell i7处理器上运行.相同的代码库也用于非Haswell处理器,其中相同的代码应替换为其SSE等效代码.我想知道有没有办法让编译器忽略非Haswell处理器上的AVX2指令.我需要这样的东西:

public void useSSEorAVX(...){
    IF (compiler directive detected AVX2)
        AVX2 code (this part is ready)
    ELSE
        SSE code  (this part is also ready)
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我在编译之前评论相关代码,但必须有一些更有效的方法来做到这一点.我正在使用Ubuntu和gcc.谢谢你的帮助.

Z b*_*son 12

除非必须,否则我认为制作单独的可执行文件并不是一个好主意.在您的情况下,您可以制作CPU调度程序.我最近为GCC和Visual studio做了这个.

假设您有一个名为productSSE和AVX 的函数.您将SSE版本放在文件product_SSE.cpp中,将AVX2版本放在文件product_AVX2.cpp中.您可以单独编译每个(例如,使用-msse2-mavx2).然后制作一个这样的模块:

extern "C" void product_SSE(float *a, float *b, float *c, int n);
extern "C" void product_AVX2(float *a, float *b, float *c, int n); 
           void product_dispatch(float *a, float *b, float *c, int n); 
void (*fp)(float* a, float *b, float *c, int n) = product_dispatch;

inline void product_dispatch(float *a, float *b, float *c, int n) {
    int iset = instrset_detect();
    if(iset==8) {
        fp = product_AVX2
    }
    else {
        fp = product_SSE
    }
    fp(a,b,c,n);
}

inline void product(float *a, float *b, float*c, int bs) {
    fp(a,b,c,n);
}
Run Code Online (Sandbox Code Playgroud)

使用较低的公共指令集(例如,使用SSE2)编译该模块.现在当你调用product时,它首先调用product_dispatch将函数指针fp设置为product_AVX2或者product_SSE然后从函数指针调用函数.你第二次打电话给product它跳转到product_AVX2product_SSE.这样您就不必拥有单独的可执行文件.

  • 编译和运行将始终在同一台机器上。因此,无需交叉复制二进制文件。此外,您的解决方案假设编译将在 AVX2 机器上完成(否则 AVX 文件将无法编译)。但无论如何+1让我学到新东西 (2认同)
  • x264 为每个具有可用于某些指令集的 asm 版本的例程使用函数指针表。`if (cpu_has_sse3) { 设置指向所有可用 sse3 例程的指针的代码块;} if (cpu_has_avx) { 设置指向所有可用 avx 例程的指针;}`。因此,您可以获得任何例程的最佳可用版本。 (2认同)

Pau*_*l R 5

如果您只想在编译时执行此操作,则可以执行以下操作:

#ifdef __AVX2__
    // AVX2 code
#elif __SSE__
    // SSE code
#else
    // scalar code
#endif
Run Code Online (Sandbox Code Playgroud)

请注意,使用gcc -mavx2 ...then 编译时__AVX2__会自动定义.同样的__SSE__.(另请注意,您可以检查编译器为使用咒语切换的任何给定命令行预先定义的内容gcc -dM -E -mavx2 - < /dev/null.)

如果你想进行运行时调度,那会更复杂一些.