原创 通用工程 2025-07-04 12:04 上海
面对数据中心异构硬件环境合池带来的管理挑战,缓解CPU分层现象是实现算力统一调度与高效利于的必经之路。
🎯 **CPU分层现象的根源在于异构硬件环境下的性能差异**:由于不同CPU架构、缓存设计、内存访问延迟(NUMA)以及指令集(如AVX)的差异,相同的应用在不同硬件上运行时会表现出不同的CPU利用率,形成“分层”现象,给容量规划和稳定性带来挑战。文章详细介绍了NUMA、Cache、降频三大类导致CPU分层的具体场景。
💡 **NUMA架构是导致内存密集型业务CPU分层的关键因素**:CPU访问同一NUMA节点内的内存比访问不同节点内存更快。当进程在跨越NUMA节点访问内存时,访存延迟增加,导致性能下降。通过`numastat`命令检测NUMA命中率,以及利用`resctrl`监控L3缓存读写数据,可以判断NUMA问题。解决方法包括CPU绑定到单一NUMA节点,或开启Linux kernel的NUMA Balancing功能,甚至采用NUMA interleave策略。
⚙️ **CPU缓存(Cache)差异影响不同CPU型号间的性能一致性**:不同CPU型号的缓存大小和结构不同,导致应用程序的工作集在缓存中的命中率产生差异。例如,缓存容量不足会频繁触发缓存行替换,降低性能。`perf`和`llcstat`工具可用于监控L3缓存命中率。缓解措施包括在目标CPU上重新编译代码,优化数据结构对齐缓存行,或利用`resctrl`进行L3缓存隔离,限制特定任务的缓存使用。
📉 **CPU降频(如因高负载或AVX指令)直接削弱计算能力**:现代CPU的动态频率调节技术和AVX指令的特性可能导致CPU在运行时降低频率,从而影响整体性能。通过监控CPU频率(如`/proc/cpuinfo`或`cpupower`命令)可发现降频现象。解决思路包括在操作系统层面或BIOS中锁定CPU频率,以确保稳定的计算性能,但需权衡功耗和散热成本。
原创 通用工程 2025-07-04 12:04 上海
面对数据中心异构硬件环境合池带来的管理挑战,缓解CPU分层现象是实现算力统一调度与高效利于的必经之路。
在这其中我们重点关注其中前三个指标:# numastat
node0 node1
numa_hit 12730959061 10270948448
numa_miss 0 571202
numa_foreign 571202 0
interleave_hit 28177 28790
local_node 12726987486 10270871809
other_node 3971575 647841
"cat_l3|cdp_l3" lscpu | grep -E
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca
cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht
…
epb cat_l3 cdp_l3 invpcid_single
然后需要使用以下命令挂载文件系统和支持功能:…..
cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
mount -t resctrl resctrl [-o cdp] /sys/fs/resctrl
在挂载之后,我们可以进入/sys/fs/resctrl/mon_data目录下其中_00和_01等就代表这不同的NUMA。mbm_local_bytes和mbm_total_bytes分别代表着读写本地NUMA域的数据和读写所有内存的数据。对于单个NUMA的命中率可以通过一下公式计算:这种方法可以用来做系统的长期监控,但是如果采用这种方法判断NUMA的使用状态有个点需要注意,就是这些计数器可能会溢出,长期监控时需要定期读取并计算差值。如果查看到某些CPU分层现象的机器,存在明显的NUMA miss率过高,便可以尝试通过合理的NUMA配置,来缓解CPU分层现象。3.3. 解决思路在观察到NUMA miss率指标异常后,可以通过CPU绑定的方式,确认NUMA的影响。CPU绑定可以使得业务始终跑在单一NUMA上,更好地利用好NUMA的特性,从而充分释放CPU的性能。具体的绑定操作可以如下,首先通过lscpu查看CPU和NUMA的关联关系。# tree /sys/fs/resctrl/mon_data
.
├── mon_L3_00
│ ├── llc_occupancy
│ ├── mbm_local_bytes
│ └── mbm_total_bytes
└── mon_L3_01
├── llc_occupancy
├── mbm_local_bytes
└── mbm_total_bytes
在进程启动前可以供过numactl来指定进程采用的NUMA节点和CPU,如只在节点0的CPU上跑节点0:#lscpu
21:04:18
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
...
...
NUMA node0 CPU(s): 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38
NUMA node1 CPU(s): 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39
numactl --cpunodebind=0 --membind=0 ./your_program
对于容器内的业务,也可以通过cgroup的方式来绑定业务到指定NUMA的CPU,指定业务只在单一NUMA的CPU列表中调度。echo "1,3,5,7,9" > /sys/fs/cgroup/cpuset/业务容器名称/ cpuset.cpus
通过以上方式,便可以保证业务实例只在指定NUMA内部调度,从而充分发挥Local node的快速优势。值得注意的是,并不是所有的业务均适合绑定NUMA的方式,假如业务的单个实例内存要求已经超过了单一NUMA节点的大小范围,这时绑定NUMA可能就带不来什么收益了,反而可能引发内存不足的潜在风险。如果对于业务内存需求较大,但是工作集的热点内存数据大多仍旧集中在单一NUMA节点范围内部,且不会频繁调度到别的节点的业务,可以Linux kernel的NUMA Balancing功能来进行优化。具体通过如下方式开启:echo 1 | sudo tee /proc/sys/kernel/numa_balancing
如果需要永久开启,保证机器重启之后依旧生效。则需要编辑 sysctl 配置文件/etc/sysctl.conf,在文件中添加以下内容:kernel.numa_balancing = 1
然后执行以下命令:sudo sysctl -p
该功能会把进程频繁访问的内存页迁移到本地NUMA,或者把当前进程迁移到访问内存所在的NUMA节点,通过此种方法来减少跨节点访问的延迟。但是整个过程需要牵扯到内存或进程的迁移,如果进程节点间调度频繁或访问内存是大块儿顺序、跨多个线程共享的场景,NUMA balancing就不太合适了,对于这种情况下,可以优先采用 NUMA interleave 策略,具体设置方式如下:numactl --interleave=all ./your_program
这种方式可以保证NUMA的均衡使用,充分利用多NUMA节点的内存带宽,提升吞吐,同时避免绑定NUMA下单个节点的内存不足或者本地优先策略导致部分部分线程频繁远程访问,造成业务性能抖动。具体采用哪种NUMA策略来缓解分层现象,需要依赖业务逻辑和NUMA miss率等观测性指标来进行抉择。4. Cache问题场景Perf可以直观的给出cache 命中率,就是其中LLC-load-misses后边的数字。尽管perf的观测能力非常强大,但是其输出的结果简单,并没有对不同的进程和CPU运行情况进行分类展示,其采样频率也比较高,性能损耗较大,通常用于debug的调试场景。在生产环境中,还有一个更加用户友好的工具llcstat。llcstat是一个基于 eBPF 的工具,相较于perf其采样频率更低,性能损耗更小,且能够汇总进程上下文信息。# perf stat -a -e LLC-load-misses,LLC-loads -- sleep 10
Performance counter stats for'system wide':
2,439,039 LLC-load-misses # 28.50% of all LL-cache
accesses
8,558,008 LLC-loads
10.001813346 seconds time elapsed
它可以在内核态直接收集数据,并按进程和 CPU 聚合显示各项指标,如 PID、进程名称、缓存引用次数、缓存未命中次数以及缓存命中率,从而能够快速、直观地诊断和定位缓存瓶颈问题,非常适用于线上环境的性能监控和故障排查。我们可以通过观察指定业务的Cache 命中率,来排查是否是Cache导致的分层现象。4.3. 解决思路Cache miss导致的CPU分层现象,本质上还是硬件结构带来的差异,很难彻底消除。问题的核心在于编译的可执行文件是相对固定的,而机器硬件结构存在差异。处理这类问题有一个较为通用的缓解方法。就是我们在不同类型CPU运行业务时,尽量在该CPU上重新编译一遍,这样编译器会更多地考虑和利用目标机器的指令集、微架构和cache结构。不过Cache miss的缓解最优解其实是在业务代码层次,如读取数组时尽量按行读取而不是按列。将数据结构对齐到缓存行边界,避免由于数据跨越多个缓存行。确保每个线程操作的数据分布在不同的缓存行中,减少缓存一致性协议的开销等等。对于Cache干扰的场景,我们可以通过resctrl进行Cache隔离的方式来处理。首先要根据3-2对resctrl进行条件检查和挂载。然后查看L3 Cache的结构:#apt update && apt install libbpf-tools
#/usr/share/bcc/tools/llcstat 1
Running for1 seconds or hit Ctrl-C to end.
PID NAME CPU REFERENCE MISS HIT%
2540 log-agent 29 18600 2000 89.25%
1535 GC Thread#4 27 26000 13200 49.23%
27753 node_exporter 27 91700 16800 81.68%
1535 GC Thread#27 33 10100 1400 86.14%
1535 VM Periodic Tas 16 2700 700 74.07%
1535 web-70628 18 6400 300 95.31%
1535 GC Thread#14 27 500 0100.00%
1535 web-70805 38 510100 162000 68.24%
1535 web-70751 6 316500 68000 78.52%
1535 web-70741 0 837400 200400 76.07%
可以看到该机器有两个L3 Cache,每个是0xfffff=20路(ways)。然后我们就可以建立资源控制组:#cat /sys/fs/resctrl/schemata
L3:0=fffff;1=fffff
mkdir /sys/fs/resctrl/mygroup sudo
编辑 schemata 文件,设置缓存和带宽的分配。例如,限制 L3 缓存只使用4路:echo "L3:0=0x0000f;" | tee /sys/fs/resctrl/mygroup/schemata
最后将任务或 CPU 分配到资源组:在我们给指定大量读写L3 Cache的任务进行隔离之后,也许会略微减少这类任务的速率,但是保证了其他混部任务不受干扰,同时提升系统总体的Cache利用率,保证了业务的稳定可预期。5. 降频问题场景#限制任务进程
#echo <PID> | tee /sys/fs/resctrl/mygroup/tasks
#限制CPU
echo 0-3 | tee /sys/fs/resctrl/mygroup/cpus
调节器(Governor)决定如何调整频率,可选项有:performance(一直保持最高频率)powersave(尽可能低频运行)ondemand(负载高时升频,低时降频)schedutil(结合调度器调整频率)C-State 最直接的控制方式是 在 BIOS/UEFI 中启用或禁用 某些级别的 C-State。C-State有多种级别,C0-Cn,其中C0代表正常运行,C1-Cn代表CPU idle状态的不同休眠程度,C后面的数值越高,CPU睡眠的越深,功耗也被降低的越多,但是恢复到运行态需要的时间也越多。可以通过以下方法查看C-State的参数:cat cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governorperformance
performance
……
performance
performance
这个文件代表当前驱动允许的最大C-State等级,如上所示,当前机器最多允许C1程度的休眠。检查产生CPU分层现象的机器是否存在降频现象需要一段时间的频率收集和比对。可以通过一下几种方法来查看。第一种方法是直接查看硬件监控面板。首先最简单有效的方法是查看moni 面板上的CPU主频信息,可以直接对比不同机器的CPU频率和单一机器不同时间的CPU频率数据。如图4所示。cat /sys/module/intel_idle/parameters/max_cstate
1
第三种方法是使用 cpupower 工具。执行 cpupower -c all frequency-info 可获取更全面的信息,包括当前频率(current CPU frequency: 当前频率)、硬件支持的频率范围以及调频策略等。若需实时监控,类似的也是可通过 watch 命令定期查询输出中的 current CPU frequency 字段。# cat /proc/cpuinfo | grep MHz
cpu MHz : 2397.279
cpu MHz : 2397.108
cpu MHz : 2397.687
cpu MHz : 2397.225
cpu MHz : 2397.232
cpu MHz : 2397.649
cpu MHz : 2397.394
cpu MHz : 2397.685
cpu MHz : 2397.377
cpu MHz : 2397.207
cpu MHz : 2397.623
cpu MHz : 2397.302
正常来说,查看监控面板来分析CPU频率对于CPU分层的现象最为方便,若仅需快速检查当前机器的状态,/proc/cpuinfo 最为便捷;但是如果需获得更详细的信息,还是推荐使用 cpupower。5.3. 解决思路在确保散热的前提下,主要可以通过锁定CPU频率的方法来解决CPU的降频导致的业务分层现象。具体可以从操作系统和硬件两个层面来锁定CPU的频率。操作系统层面可以使用以下方法来配置。# cpupower -c all frequency-info
analyzing CPU 0:
driver: intel_pstate
CPUs which run at the same hardware frequency: 0
CPUs which need to have their frequency coordinated by software: 0
maximum transition latency: Cannot determine or is not supported.
hardware limits: 800 MHz - 3.80 GHz
available cpufreq governors: performance powersave
current policy: frequency should be within 800 MHz and3.80 GHz.
The governor "performance" may decide which speed to use
within this range.
current CPU frequency: Unable to call hardware
current CPU frequency: 2.90 GHz (asserted by call to kernel)
boost state support:
Supported: yes
Active: yes
通过硬件锁频则通常需要进入BIOS找到Package Power Limit Contol相关的选项,设置为指定频率,不过不同厂商的设置方式大相径庭,具体操作方法建议查阅主板的相关说明,或者参考厂商的技术支持文档。面对CPU降频导致的分层现象,前期可以采用操作系统锁频的方式,灵活快捷,无需重启,适合临时问题验证,但可能被系统温控覆盖;确认问题之后后期还是建议BIOS锁频,更稳定彻底,适合长期使用,适合生产环境持久保障。虽然CPU锁频可以避免CPU 频率波动会带来性能抖动,提升系统的稳定性。但是另一方面,高频运行意味着持续高功会带来更多的电量和散热需求,这样将会带来电费成本的增加,可以根据业务实际情况做取舍。6. 总结和展望步骤1:查看可用频率
#cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
步骤2:设置固定频率
#for cpu in /sys/devices/system/cpu/cpu*/cpufreq; do
echo "3500000" | sudo tee $cpu/scaling_min_freq
echo "3500000" | sudo tee $cpu/scaling_max_freq
done
步骤3:验证设置
#watch -n 1 "cat /proc/cpuinfo | grep 'MHz'"
AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。
鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑