把实时线程独占一个 CPU 后,仍可能发现执行时间随“其他核在干什么”而波动。原因是核心并不独占整台芯片:同一 NUMA 节点中的 CPU 可能共享末级缓存(LLC)、内存控制器和互连带宽;跨节点访问还会经过更长路径。另一个核心上大规模 memcpy、GPU DMA、数据库或网络包处理,都可能让实时线程的缓存命中率下降、内存访问排队变长。
CPU 亲和性不等于内存亲和性
Linux 常用“首次触碰”分配策略:一页虚拟内存第一次被实际访问时,物理页通常会分配在执行该访问的 NUMA 节点。若启动线程在 CPU 0 上分配/触碰缓冲区,后来把实时线程迁到另一个节点,关键数据就可能长期跨节点访问。线程绑核、数据预触碰和内存策略应作为同一件事设计。
先看拓扑,再谈优化
在多路系统上,先查看节点、CPU 和距离矩阵;再把线程与其工作集绑定到同一节点。numactl 可以作为实验工具验证亲和性假设,但生产环境更应将策略固化在服务启动、cgroup 或资源管理器配置中。
1 | numactl --hardware |
该示例表示同时约束 CPU 和内存节点。是否应强制绑定、允许 fallback,取决于容量与故障策略;如果节点内存耗尽,硬性策略可能让程序直接失败,这也是需要提前设计的行为。
用对抗负载量最坏执行时间
空载时 CPU 本地性看起来常常没有区别。更有意义的测试是:在相邻核发起持续内存带宽压力,或运行实际视频/GPU DMA 负载,同时记录实时线程的周期执行时间和 cache miss 指标。若长尾随邻核负载增长,说明瓶颈不在调度器,而在共享资源。
优化选择包括:调整 CPU/NUMA 布局、将热点数据压缩到缓存、减少不必要的拷贝、把大吞吐任务移动到远离实时核的节点,必要时使用硬件支持的 resource control。目标不是让一切绝对隔离,而是对共享资源造成的最坏执行时间有可验证的上界。
参考:Resource Control · numa(7)