本文介绍了英特尔JCC错误-用于缓解的前缀有何影响?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

英特尔recommends使用指令前缀缓解JCC错误的性能后果。

如果使用/QIntel-jcc-erratum编译MSVC,则遵循建议,并插入前缀指令,如下所示:

3E 3E 3E 3E 3E 3E 3E 3E 3E 48 8B C8   mov rcx,rax ; with redundant 3E prefixes

They sayMSVC在前缀不可用时求助于NOPS。

Clang有-mbranches-within-32B-boundaries选项,如果需要,它更喜欢nop,多字节(https://godbolt.org/z/399nc5Msq通知xchg ax, ax)

3E前缀的后果是什么,具体是:

  • 为什么英特尔推荐这种方式,而不是多字节NOPS?
  • 未受影响的CPU会有什么后果?
  • 据报道,AMD上的/QIntel-jcc-erratum程序运行得更快,可能的解释是什么?

NOP

推荐答案是单独的指令,必须分别解码并通过流水线。始终最好使用前缀填充指令以实现所需的对齐,而不是像What methods can be used to efficiently extend instruction length on modern x86?中所讨论的那样插入NOP(但只能以不会在某些无法处理大量前缀的CPU上造成重大停顿的方式进行)。

也许Intel认为工具链在这种情况下这样做是值得的,因为它实际上将位于内部循环内,而不仅仅是内部循环外部的NOP。(将前缀添加到前一条指令相对简单。)


我现在有了一些数据点。AMD FX 8300上/QIntel-jcc-erratum的基准测试结果

特定基准测试的速度下降了十进制数量级,其中英特尔Skylake在同一基准测试中的收益约为20%。这与Peter的评论一致:

尽管推土机家族确实过时了,但我认为我承受不起如此大的影响。我还担心其他CPU可能会以同样的方式被额外的前缀卡住。因此,我的结论是而不是/QIntel-jcc-erratum用于一般目标软件。除非在特定的翻译单位中启用它并动态调度到那里,这在大多数情况下都是一件非常麻烦的事情。


在MSVC上可能安全的一件事是停止使用/Os标志。发现/Os标志至少:

  • 避免跳转表而支持条件跳转
  • 避免循环开始填充

尝试以下示例(https://godbolt.org/z/jvezPd9jM):

void loop(int i, char a[], char b[])
{
    char* stop = a + i;
    while (a != stop){
        *b++ = *a++;
    }
}

void jump_table(int i, char a[], char b[])
{
    switch (i)
    {
                            case 7: 
            a[6] = b[6];    case 6: 
            a[5] = b[5];    case 5: 
            a[4] = b[4];    case 4: 
            a[3] = b[3];    case 3: 
            a[2] = b[2];    case 2: 
            a[1] = b[1];    case 1: 
            a[0] = b[1];    case 0:  break;
            default: __assume(false);
    }
}

这会导致更频繁地遇到JCC性能问题(避免跳表会产生一系列JCC,避免对齐会导致小于16b的小循环有时还会触及边界)

这篇关于英特尔JCC错误-用于缓解的前缀有何影响?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 23:22