我正在调整我的程序以实现低延迟。
我有一个严格的计算函数 calc();大量使用 SIMD 浮点指令。
我测试了 calc() 的性能;使用 perf 命令。它表明这个 calc 函数平均使用 ~10k 指令和 ~5k cpu 周期。
但是,当我把这个 calc 函数放在旋转等待之后时,就像
while(true) {
if (!flag.load(std::memory_order_acquire)) {
continue;
}
calc();
}
calc 部分使用了大约 10k 个周期。和其他性能计数器,如
l1d-cache-misses
、llc-misses
、branch-misses
和 instructions
保持不变。
谁能帮我解释这是怎么发生的,我应该怎么做才能避免这种情况?我的意思是尽可能快地保持计算功能。
此外,我还有两个有趣的发现:
如果我在很短的时间内(小于 1 毫秒)设置了标志变量。我没有注意到函数计算有任何性能下降。
如果我在自旋等待中间添加一些垃圾 simd 浮点计算。我可以达到预期的表现。
我的CPU是13900K。我还在 12900K 和 Ice Lake CPU(如 Xeon 8368)上进行了测试。看起来它们具有相同的行为。
我从
Optimization Reference Manual
注意到有一个叫做Thread Director
的东西可以在运行时自动检测线程类,还有一个特殊的类叫做 Pause (spin-wait) dominated code
。我不知道这是否相关,但看起来在一段时间后,CPU 检测到该线程处于自旋等待循环中,然后减少了分配给该线程的资源?
我正在测试 redhat 实时内核。从 bios 关闭高效核心,将 cpu 亲和力设置为特定核心 ID,并将 secudle 设置为 FIFO 并将优先级设置为 99。此外,我已尽可能阻止所有中断。并将本地定时器中断每秒减少一次。
我还尝试在自旋循环中间添加 _mm_pause()(根据优化参考手册的建议)。但它没有帮助。
我从一个特殊供应商那里购买了 13900k 服务器并使用了液体编码系统。将所有 8 个性能核心超频至 5.8GHz。系统启动命令行为
[root@hft-13900k ~]# cat /proc/cmdline
BOOT_IMAGE=(hd0,gpt2)/vmlinuz-4.18.0-425.13.1.rt7.223.el8_7.x86_64 root=/dev/mapper/rhel-root ro crashkernel=auto rd.lvm.lv=rhel/root rhgb quiet isolcpus=0-6 rcu_nocbs=0-6 spectre_v2=off mitigations=off iommu=off intel_iommu=off tsc=reliable pcie_port_pm=off ipv6.disable=1 ipmi_si.force_kipmid=0 acpi_irq_nobalance rcu_nocb_poll clocksource=tsc selinux=0 intel_pstate=disable pcie_aspm=performance nosoftlockup audit=0 nmi_watchdog=0 mce=ignore_ce nohz=on intel_idle.max_cstate=0 processor.max_cstate=0 idle=poll transparent_hugepage=never hpet=disabled noht nohz_full=0-6 skew_tick=1