本博客的内容由英特尔公司的Gautham Beeraka提供。
英特尔最近宣布 跳转条件码(JCC)勘误表 它的一些处理器可能会出现这种情况。MSVC团队一直在与英特尔合作,在编译器中提供一个软件修复程序,以减轻防止出现错误的微码更新对性能的影响。
介绍
关于JCC勘误表,有三件事你应该知道:
- 勘误表是什么,它对你有什么影响。
- 微码更新,以防止错误,如果你有它和它的副作用。
- MSVC编译器支持减轻微码更新的副作用。
下面将对每个主题进行解释。
JCC勘误表
上面提到的英特尔白皮书中列出的处理器有一个异常,在某些情况下可能会出现这种异常,这些情况涉及到覆盖缓存线边界的跳转指令。这种不稳定会导致在这些处理器上运行的软件出现不可预知的行为。如果您的软件在这些处理器上运行,则会受到此错误的影响。
微码更新
应用微码更新(MCU)可以防止JCC错误。MCU的工作原理是防止覆盖或结束于32字节边界的跳转指令(如下图所示)被缓存在解码的uop缓存中。MCU影响条件跳转、宏融合条件跳转、直接无条件跳转、间接跳转、直接/间接调用和返回。
MCU将通过Windows Update分发。一旦我们有了更多关于Windows更新的信息,我们就会更新这个博客。请注意,MCU并不特定于Windows,也适用于其他操作系统。
应用MCU可以降低在修补过的机器上运行的软件的性能。根据我们的测量,我们看到影响在0-3%之间。对一些异常微基准点的影响更大。
MSVC编译器中的软件缓解
为了减轻性能影响,开发人员可以使用 /QIntel jcc勘误表 在MSVC编译器中切换。我们观察到,使用此修复程序重建后,性能退化变得可以忽略不计。根据我们的测量,这个开关可以增加大约3%的代码大小。
如何启用软件缓解?
从VisualStudio2019版本16.5预览版2开始,开发人员可以应用软件缓解对MCU性能的影响。要为代码启用JCC勘误表的软件缓解,只需在项目属性页的“代码生成”部分下选择“是”:
一些未记录的编译器标志也可用于限制软件缓解的范围,如下所示。这些标志可以用于实验,但我们不承诺在将来的版本中为它们提供服务。
- /d2QIntel jcc勘误表部分 –这仅在函数中的循环内应用缓解。
- /d2QIntel jcc勘误表:
- /d2QIntel jcc勘误表部分:
要启用这些标志,请将它们添加到项目属性页“命令行”部分下的“附加选项”中:
所有这些开关只在发布版本中工作,并且与 /清除 开关。如果有多个 /d2QIntel jcc勘误表* 在给定开关的情况下,完全处理(所有分支)优于部分(仅循环分支)处理。如果任何开关指定函数文件,则处理仅限于这些函数。
软件缓解的作用是什么?
编译器中的软件缓解方法检测代码中所有受影响的跳转(覆盖或结束于32字节边界的跳转),并将它们对齐以该边界开始。这是通过在跳转之前向指令添加良性段覆盖前缀来实现的。结果指令的大小增加,但小于15字节。在不能添加前缀的情况下,使用nop。下面的示例显示了在启用和禁用缓解时编译器如何生成代码。
示例C++代码:
for (int i = 0; i < length; i++) { sum += arr[i] + c; }
不带QIntel jcc勘误表的代码 (/O2/FAsc) |
带/QIntel jcc勘误表的代码 (/O2/FAsc/QIntel jcc勘误表) |
$LL8@test1:
00010 44 8b 0c 91号 mov r9d,双字PTR[rcx+rdx*4] 00014 48 ff c2 公司rdx 00017 45 03 c8号 添加r9d、r8d 0001a 41 03 c1 添加eax,r9d 0001d号 49 3b d2号 凸轮轴位置rdx,r10 00020 7摄氏度 jl短$LL8@test1 |
$LL8@test1:
00010 3e 3e 3e 44 8b 0c 91号 压敏电阻 r9d,双字PTR[rcx+rdx*4] 00017 48 ff c2 股份有限公司 黑索今 0001a 45 03 c8型 添加 r9d、r8d 0001d 41 03 c1 添加 eax,r9d型 00020 49 3b d2号 化学机械抛光 黑索今,r10 00023 7c电子束 吉隆坡 短$LL8@test1 |
在上面的示例中,CMP和JL指令是宏融合的,并覆盖32字节的边界。缓冲区填充块中的第一条指令,即带有0x3E前缀的MOV指令,以使CMP指令在32字节边界上开始。
什么是表演故事?
我们在MSVC编译器中评估了MCU和fix对性能的影响。下面所述的数字使用以下测试PC配置。
处理器 –英特尔® 核心™ i9 9900K@3.60GHz频率
操作系统 –使用适用于此处理器的MCU的专用Windows构建。
基准测试套件 –规格CPU® 2017
根据我们的测量,我们看到应用MCU后的回归范围为0-3%。我们还看到一些异常微基准上的回归上升到10%。
通过 /QIntel jcc勘误表 MSVC编译器中的开关使得回归可以忽略不计。此切换将全局缓解应用于使用它构建的所有模块,并增加代码大小。我们测量了平均3%%代码大小膨胀。
我们测量了仅在通过 /d2QIntel jcc勘误表部分 switch也使得性能退化可以忽略不计,但代码大小增加的幅度较小。我们测量了平均1.5%%的代码大小膨胀和部分缓解。通过将缓解措施仅应用于通过 /d2QIntel jcc勘误表:
我们还测量了 /QIntel jcc勘误表 打开不受异常影响的处理器可以忽略不计。但是,由于代码基差异很大,我们建议开发人员评估 /QIntel jcc勘误表 在应用程序和工作负载的上下文中。
闭幕词
如果您的软件可以在处理器受JCC勘误表影响的机器上运行,并且可以在带有MCU的Windows版本上运行,那么我们建议您分析代码并检查性能退化。你可以用 Windows性能套件 或 英特尔® VTune™ 轮廓仪 来分析你的代码。您可以按照英特尔白皮书中的步骤检测MCU是否影响性能。如果受影响,请使用重新编译 /QIntel jcc勘误表 或上面列出的其他开关来减轻影响。
您的反馈是提供最佳体验的关键。如果您有任何问题,请随时问我们下面。你也可以把你的意见发送给我们 电子邮件 . 如果您在体验中遇到问题或有改进建议,请 报告问题 或者通过 开发者社区 . 你也可以在Twitter上找到我们 @视觉 .