如果我有一个受Intel jcc erratum约束的芯片,我如何在 gcc 中启用缓解(它调整分支位置以避免有问题的对齐),以及哪些 gcc 版本支持它?
KbL i7-8550U
我正在研究 uops-cache 的行为并遇到了关于它的误解。
如英特尔优化手册2.5.2.2(我的)中所述:
解码的 ICache 由 32 组组成。每组包含八种方式。 每路最多可容纳六个微操作。
——
Way 中的所有微操作表示在代码中静态连续的指令,并且它们的 EIP 位于相同的对齐 32 字节区域内。
——
最多三种方式可以专用于相同的 32 字节对齐块,从而允许在原始 IA 程序的每个 32 字节区域中缓存总共 18 个微操作。
——
无条件分支是 Way 中的最后一个微操作。
情况1:
考虑以下例程:
uop.h
void inhibit_uops_cache(size_t);
Run Code Online (Sandbox Code Playgroud)
uop.S
align 32
inhibit_uops_cache:
mov edx, esi
mov edx, esi
mov edx, esi
mov edx, esi
mov edx, esi
mov edx, esi
jmp decrement_jmp_tgt
decrement_jmp_tgt:
dec rdi
ja inhibit_uops_cache ;ja is intentional to avoid Macro-fusion
ret
Run Code Online (Sandbox Code Playgroud)
为了确保例程的代码实际上是 32 字节对齐的,这里是 asm …
这个问题曾经是这个(现已更新)问题的一部分,但它似乎应该是另一个问题,因为它无助于获得另一个问题的答案。
我的出发点是一个循环进行 3 个独立的添加:
for (unsigned long i = 0; i < 2000000000; i++) {
asm volatile("" : "+r" (a), "+r" (b), "+r" (c), "+r" (d)); // prevents C compiler from optimizing out adds
a = a + d;
b = b + d;
c = c + d;
}
Run Code Online (Sandbox Code Playgroud)
当这个循环没有展开时,它在 1 个周期内执行(这是预期的:它包含 4 条指令:3 个加法和宏融合增量/跳转;所有这些都可以在端口 0 上在一个周期内执行, 1、5 和 6)。展开此循环时,性能令人惊讶,并且往往比未展开的版本慢 25%,这可能是由于 uops 调度,如上一个问题的评论中所建议的。
在这个问题中,我不是在问性能,而是在问为什么在某些情况下,uop 来自 MITE(传统管道),而在其他情况下,来自 DSB(uop 缓存)。(请注意,我使用的是禁用 LSD(循环流检测器)的 Skylake)
实验上,当跳转在 32 字节上没有完全对齐时,uop 是从 MITE …
英特尔推送微码更新以修复名为“跳转条件代码 (JCC) 勘误表”的错误。由于在某些条件下禁用将代码放入 ICache,更新微码导致某些操作效率低下。
已发布的文档,标题为跳转条件代码勘误的缓解措施不仅列出了JCC,还列出了:无条件跳转、条件跳转、宏融合条件跳转、调用和返回。
MSVC 开关/QIntel-jcc-erratum文档提到:
在 /QIntel-jcc-erratum 下,编译器检测跨越或结束于 32 字节边界的跳转和宏融合跳转指令。
问题是:
Python 3.12 两天前发布,包含多项新功能和改进。它声称它比以往任何时候都快,所以我决定尝试一下。我用新版本运行了一些脚本,但速度比以前慢。我尝试了各种方法,每次都简化我的代码,试图找出导致其运行缓慢的瓶颈。然而,到目前为止我还没有成功。最后,我决定测试一个简单的 for 循环,如下所示:
import time
def calc():
for i in range(100_000_000):
x = i * 2
t = time.time()
calc()
print(time.time() - t)
Run Code Online (Sandbox Code Playgroud)
在我的机器上,Python 3.11.5 上需要 4.7 秒,Python 3.12.0 上需要 5.7 秒。在其他机器上尝试也得到了类似的结果。
那么为什么在最新版本的Python中它会变慢呢?