0

英特尔工程师写道,我们应该使用 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 的情况:

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

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

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

James R.有一篇文章“如何检测 Knights Landing AVX-512 支持(英特尔® 至强融核™ 处理器)”,更新于 2016 年 2 月 22 日,但它只关注 Knights Landing 上可用的特定新指令。所以关于 VEX 转换仍然不是很清楚。

很高兴知道英特尔是否计划实施 CPUID 位来显示非 VEX 状态是否成本高昂?例如:

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

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

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

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。

请指教。

4

1 回答 1

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; }    
};
于 2017-06-12T11:55:01.933 回答