linux下/proc/cpuinfo中processor行数为逻辑核数,physical id去重得物理cpu个数,cpu cores×physical id个数为物理核心总数,core id配合siblings可判断是否启用超线程。

Linux下用/proc/cpuinfo解析物理核与逻辑核
Linux系统里,/proc/cpuinfo是获取CPU拓扑最直接、最可靠的方式。它不依赖额外库,也不需要root权限,但要注意:它返回的是逻辑处理器(包括超线程)的列表,不是物理核心数。
关键识别字段:processor表示逻辑核编号;core id和cpu cores配合可推导物理核心;physical id标识CPU插槽(多路服务器场景)。
- 读取
/proc/cpuinfo后按physical id和core id去重,即可得物理核心总数 - 统计
processor行数即为逻辑核心数(nproc命令底层也这么干) - 注意某些ARM平台可能缺失
core id,此时应优先信任cpu cores字段(每颗物理CPU声明的核心数)
Windows下用GetLogicalProcessorInformation获取拓扑
Windows没有统一文本接口,必须调用WinAPI。推荐用GetLogicalProcessorInformation而非已废弃的GetSystemInfo——后者只返回逻辑核总数,无法区分物理/逻辑关系。
该函数返回SYSTEM_LOGICAL_PROCESSOR_INFORMATION数组,每个元素带Relationship字段,需遍历过滤出RelationProcessorCore类型:
- 每个
RelationProcessorCore结构体的ProcessorMask是一个位掩码,1的个数即该物理核上的逻辑线程数(通常是1或2) - 统计
RelationProcessorCore元素个数 = 物理核心数;对所有ProcessorMask中1的个数求和 = 逻辑核心数 - 务必检查返回值和
GetLastError(),常见错误ERROR_INSUFFICIENT_BUFFER需先调用一次获取所需缓冲区大小
C++跨平台封装时别直接信std::thread::hardware_concurrency()
std::thread::hardware_concurrency()常被误认为“物理核心数”,其实它返回的是**系统建议的并发线程上限**,在Linux上通常等于逻辑核数,在Windows上也可能受组策略或容器限制而返回0或错误值。
- 它不区分超线程,也不提供拓扑信息,仅适合做线程池初始大小参考
- 某些嵌入式或虚拟化环境(如WSL2、Docker)可能返回1或远低于实际值,不能用于CPU绑定或亲和性设置
- 若需精确控制,必须绕过标准库,走OS原生接口(前两节所述)
获取缓存层级与拓扑关系时警惕cpuid指令的复杂性
想拿到L1/L2/L3缓存大小、共享关系或NUMA节点,cpuid指令是终极手段,但C++里手动执行它风险高:需内联汇编、处理不同厂商编码规则(Intel/AMD扩展不同)、解析嵌套的缓存描述符。
- 除非写高性能库或调试工具,否则优先用OS接口:
/sys/devices/system/cpu/cpu*/topology/(Linux)或GetLogicalProcessorInformationEx(Windows 10+) - 例如Linux下读
/sys/devices/system/cpu/cpu0/topology/core_siblings_list可获与CPU0共享物理核的逻辑核列表 - 直接调
cpuid容易因未校验eax输入值导致段错误,且现代CPU的缓存拓扑可能动态变化(如Intel Speed Select)
真正难的不是读数据,而是理解“物理核”“逻辑线程”“共享缓存域”“NUMA节点”四者之间的嵌套关系——同一份/proc/cpuinfo输出,不同业务场景要提取的字段完全不同。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











