与 AVX/AVX2 一起使用的最低 OS X 版本是什么?

TAB*_*ATA 3 macos sse avx avx2

我有一个图像绘制例程,为 SSE、SSE2、SSE3、SSE4.1、SSE4.2、AVX 和 AVX2 编译多次。我的程序通过检查 CPUID 标志来动态调度这些二进制变体之一。

在 Windows 上,我检查 Windows 版本,如果操作系统不支持 AVX/AVX2 调度,则禁用它们。(例如,仅 Windows 7 SP1 或更高版本支持 AVX/AVX2。)

我想在 Mac OS X 上做同样的事情,但我不确定哪个版本的 OS X 支持 AVX/AVX2。

请注意,我想知道的是与 AVX/AVX2 一起使用的 OS X 的最低版本。不支持 AVX/AVX2 的机器型号。

Z b*_*son 5

为了检测指令集功能,我参考了两个源文件:

  1. 神秘的cpu_x86.cpp
  2. Agner Fog 的instrset_detect.cpp

如果您的操作系统支持 AVX 和其他功能,这两个文件都会告诉您如何通过 AVX2 以及 XOP、FMA3、FMA4 检测 SSE。

我习惯了 Agner 的代码(MSVC、GCC、Clang、ICC 的一个源文件),所以让我们先看一下。

instrset_detect.cpp以下是检测 AVX 的相关代码片段:

iset = 0;                                              // default value
int abcd[4] = {0,0,0,0};                               // cpuid results
cpuid(abcd, 0);                                        // call cpuid function 0
//....
iset = 6;                                              // 6: SSE4.2 supported
if ((abcd[2] & (1 << 27)) == 0) return iset;           // no OSXSAVE
if ((xgetbv(0) & 6) != 6)       return iset;           // AVX not enabled in O.S.
if ((abcd[2] & (1 << 28)) == 0) return iset;           // no AVX
iset = 7;                                              // 7: AVX supported
Run Code Online (Sandbox Code Playgroud)

xgetbv定义为

// Define interface to xgetbv instruction
static inline int64_t xgetbv (int ctr) {    
#if (defined (_MSC_FULL_VER) && _MSC_FULL_VER >= 160040000) || (defined (__INTEL_COMPILER) && __INTEL_COMPILER >= 1200) // Microsoft or Intel compiler supporting _xgetbv intrinsic

    return _xgetbv(ctr);                                   // intrinsic function for XGETBV

#elif defined(__GNUC__)                                    // use inline assembly, Gnu/AT&T syntax

   uint32_t a, d;
   __asm("xgetbv" : "=a"(a),"=d"(d) : "c"(ctr) : );
   return a | (uint64_t(d) << 32);

#else  // #elif defined (_WIN32)                           // other compiler. try inline assembly with masm/intel/MS syntax

  //see the source file
}
Run Code Online (Sandbox Code Playgroud)

我没有包含该cpuid函数(请参阅源代码),并且删除了非 GCC 内联汇编xgetbv以使答案更短。

以下是detect_OS_AVX()来自 Mysticial 的cpu_x86.cpp用于检测 AVX 的信息:

bool cpu_x86::detect_OS_AVX(){
    //  Copied from: http://stackoverflow.com/a/22521619/922184

    bool avxSupported = false;

    int cpuInfo[4];
    cpuid(cpuInfo, 1);

    bool osUsesXSAVE_XRSTORE = (cpuInfo[2] & (1 << 27)) != 0;
    bool cpuAVXSuport = (cpuInfo[2] & (1 << 28)) != 0;

    if (osUsesXSAVE_XRSTORE && cpuAVXSuport)
    {
        uint64_t xcrFeatureMask = xgetbv(_XCR_XFEATURE_ENABLED_MASK);
        avxSupported = (xcrFeatureMask & 0x6) == 0x6;
    }

    return avxSupported;
}
Run Code Online (Sandbox Code Playgroud)

神秘显然是从这个答案中得出这个解决方案的。

请注意,两个源文件基本上执行相同的操作:检查 OSXSAVE 位 27,检查 CPUID 中的 AVX 位 28,检查xgetbv.