如何检测 Xeon Phi (Knights Landing)

Posted

技术标签:

【中文标题】如何检测 Xeon Phi (Knights Landing)【英文标题】:How to detect a Xeon Phi (Knights Landing) 【发布时间】:2017-06-09 20:12:13 【问题描述】:

英特尔工程师写道,我们应该使用 VZEROUPPER/VZEROALL 来避免在所有处理器(包括未来的 Xeon 处理器,但不是 Xeon Phi)上昂贵地转换到非 VEX 状态:https://software.intel.com/pt-br/node/704023

人们也测了下,发现 VZEROUPPER 和 VZEROALL 在 Knights Landing 上很贵:

64 位模式下两条指令的 36 个时钟周期(32 位模式下 30 个时钟)。

参见上面的链接。

所以如果我刚刚使用了 ymm0 和 ymm1,我的代码如下:

if [we are running on a Xeon Phi]
     vpxor       ymm0,ymm0,ymm0
     vpxor       ymm1,ymm1,ymm1
else
     vzeroall
endif

如何检测 Xeon Phi(Knights Landing 和更高版本的 Xeon Phi 处理器)来实现上述代码?

我们现在有以下关于 VZEROUPPER/VZEROALL 的情况:

    在 Xeon Phi Knight Landing 上,这些指令在 64 位模式下的两条指令均 36 个时钟周期(32 位模式下为 30 个时钟周期)不需要这些指令,而且成本非常高。 这些指令非常便宜,在 Xeon 和 Core 处理器 (Skylake/Kaby Lake) 上是必需的,在可预见的未来 Xeon 也需要这些指令,以避免昂贵的过渡到非 VEX 状态。

广告材料声称 Xeon Phi (Knights Landing) 与其他 Xeon 处理器完全兼容。

为了避免 VZEROUPPER/VZEROALL,是否有可靠的方法来检测 Xeon Phi?

有一篇文章"How to detect Knights Landing AVX-512 support (Intel® Xeon Phi™ processor)" by James R., Updated February 22, 2016,但它只关注在骑士登陆时可用的特定新指令。所以关于 VEX 转换仍然不是很清楚。

如果知道英特尔是否计划实施 CPUID 位来显示非 VEX 状态是否成本高昂,那就太好了?例如:

位设置为 0 - VEX 状态转换成本高,但 VZEROUPPER/VZEROALL 成本低,应用于清除状态; 位设置为 1 - 没有转换损失,不需要 VZEROUPPER/VZEROALL。

上面提到的关于检测 Knights Landing 的文章建议检查 Knights Landing 中介绍的位 AVX-512F+CD+ER+PF。

所以代码建议一次检查所有这些位,如果都设置好了,那么我们就在骑士登陆了:

uint32_t avx2_bmi12_mask = (1 << 16) | // AVX-512F
                           (1 << 26) | // AVX-512PF
                           (1 << 27) | // AVX-512ER
                           (1 << 28);  // AVX-512CD

很高兴知道英特尔是否计划在不久的将来将这些所有位添加到简单的 Xeon(非 Phi)或 Core 处理器中,因此它们也将支持 AVX-512F+CD+ER+PF 功能在骑士登陆中引入?

如果 Xeon 和 Core 处理器支持 AVX-512F+CD+ER+PF,我们将无法区分 Xeon 和 Xeon Phi。

请指教。

【问题讨论】:

你在编译时肯定知道目标 CPU,所以你可以只使用预处理器宏? 对,但是您可以编译优化函数的特定于 CPU 的版本并在运行时使用调度程序——这就是英特尔在其优化库中所做的。这样您的代码就会更有效率,因为它不需要进行任何运行时检查(除了第一次调用调度程序)。 这有帮助吗:software.intel.com/en-us/articles/… ? 你不能检查支持的功能然后cpuid.family == Bsandpile.org/x86/cpuid.htm 需要注意的一点是 Skylake Xeon (Purley) 将支持 AVX512 - 我不知道它是否有 VEX 切换惩罚。 【参考方案1】:

如果您特别想检查是否在 KNL(而不是更笼统的“我正在运行的 CPU 是否具有功能 X?”),您可以通过查看“扩展系列”、“系列”来做到这一点在使用 %eax==1 和 %ecx == 0 调用 cpuid 后,%eax 中的“模型”字段。类似下面的 C++ 代码可以完成这项工作。

但是,正如其他人含蓄指出的那样,这是一项非常具体的测试,例如,在未来的 Knights 核心上会失败,因此您可能会更好地按照建议执行并检查 AVX-512 功能不在至强,所以 AVX512-ER 和 AVX512-PF。 (当然,这样的指令可能会出现在未来的 Xeons 中,所以从长远来看这并不能保证,但是引用凯恩斯的话:“从长远来看,我们都死了”:-))

class cpuidState

    uint32_t orig_eax;                      /* Values sent in to the cpuid instruction */
    uint32_t orig_ecx;

    uint32_t eax;                           /* Values received back from it. */
    uint32_t ebx;
    uint32_t ecx;
    uint32_t edx;

    void cpuid()
    
        __asm__ __volatile__("cpuid"
                             : "+a" (eax), "=b" (ebx), "+c" (ecx), "=d" (edx));
    

    void update (uint32_t eaxVal, uint32_t ecxVal)
    
        orig_eax = eaxVal;
        orig_ecx = ecxVal;
        eax      = eaxVal;
        ecx      = ecxVal;
        cpuid();
    

    void ensureCorrectLeaf(uint32_t eaxVal, uint32_t ecxVal)
    
        if (orig_eax != eaxVal || orig_ecx != ecxVal)
            update (eaxVal, ecxVal);
    

 public:
    cpuidState() : orig_eax (-1), orig_ecx(-1)  

    // Include the Extended Model in the test. Without it we see some Xeons as KNL :-(
    bool onKNL()             ensureCorrectLeaf(1,0); return (eax & 0x0f0ff0) == 0x50670;     
;

【讨论】:

以上是关于如何检测 Xeon Phi (Knights Landing)的主要内容,如果未能解决你的问题,请参考以下文章

Xeon phi 卸载模式如何利用线程并行和矢量化

如何使用 GCC 5.1 和 OpenMP 将工作卸载到 Xeon Phi

在 xeon-phi 上引导自定义内核

Xeon-Phi 从主机 openMP 并行区域异步卸载

无法解释的 Xeon-Phi 开销

intel xeon phi 常见错误记录