linux通过/sys/devices/system/cpu/cpu*/topology/目录解析物理核心与逻辑核映射,windows依赖getlogicalprocessorinformation()获取分层拓扑,macos仅能通过sysctl粗略推断,跨平台需动态验证超线程比例且考虑热插拔。

Linux下用/sys/devices/system/cpu/解析物理核心与逻辑核映射
Linux内核把CPU拓扑信息以文件形式暴露在/sys/devices/system/cpu/下,比调用sysconf(_SC_NPROCESSORS_ONLN)这类接口更可靠——后者只返回在线逻辑核数,不区分物理核心和超线程关系。
关键路径:/sys/devices/system/cpu/cpu*/topology/core_id表示该逻辑核所属物理核心编号;/sys/devices/system/cpu/cpu*/topology/physical_package_id表示所属CPU插槽(socket);/sys/devices/system/cpu/cpu*/topology/thread_siblings_list直接给出同属一个物理核心的所有逻辑核列表(逗号分隔,支持范围如0-1)。
- 遍历
/sys/devices/system/cpu/cpu[0-9]*/目录,跳过offline状态的CPU(检查/sys/devices/system/cpu/cpu*/online是否为1) - 读取每个
cpuN/topology/thread_siblings_list,解析后按物理核心分组,就能得到完整的超线程映射 - 注意:某些ARM平台或容器环境可能缺失
topology/子目录,此时需回退到lscpu命令输出解析(但不可用于程序内嵌逻辑)
Windows上用GetLogicalProcessorInformation()获取分层拓扑
Windows没有统一的procfs式接口,必须用GetLogicalProcessorInformation()——它返回SYSTEM_LOGICAL_PROCESSOR_INFORMATION数组,每项含Relationship字段标识层级关系(RelationProcessorCore、RelationNumaNode、RelationCache等)。
关键点在于:同一ProcessorMask下的所有位,若出现在RelationProcessorCore条目中,就属于同一个物理核心;若多个条目共享相同ProcessorMask但Relationship不同,则说明存在NUMA或缓存层级嵌套。
- 必须循环调用两次:第一次传
NULL获取所需缓冲区大小,第二次分配内存再调用 -
ProcessorMask是KAFFINITY类型(64位整数),每个bit代表一个逻辑处理器,需用_BitScanForward或__popcnt64统计激活位数 - 容易漏掉的是
RelationGroup:在超过64核的系统上,Windows会把逻辑核分组,GROUP_AFFINITY结构体才真正描述跨组掩码,忽略它会导致识别出错
macOS无法直接获取超线程映射,只能靠sysctl组合推断
macOS内核不暴露物理核心与逻辑核的显式映射关系。sysctl hw.ncpu返回总逻辑核数,hw.physicalcpu返回物理核心数,hw.logicalcpu同hw.ncpu,但三者相减并不能安全得出超线程数——M系列芯片无超线程,Intel机型有,且部分型号存在混合核心(Performance/Efficiency),hw.physicalcpu_max也不等于实际启用的核心数。
- 唯一可行方式是结合
sysctl hw.packages(插槽数)、hw.physicalcpu、hw.logicalcpu做粗略判断:若logicalcpu / physicalcpu == 2且厂商为Intel,大概率启用了超线程 - 无法获得每个逻辑核对应的物理核心ID,也无法区分P/E核——Apple未提供用户态API支持此粒度查询
- 试图读取
/proc或/sys路径会失败,macOS根本没有这些目录
跨平台封装时别硬编码“超线程=2”,要动态验证
很多C++库(比如tbb、folly)在初始化线程池时默认按std::thread::hardware_concurrency()分配,但这只是逻辑核数,没反映真实拓扑。若想做亲和性调度或NUMA感知分配,必须自行解析拓扑,且不能假设超线程总是2倍关系。
- Intel Atom、某些至强可扩展处理器支持1:4超线程(4线程/核心),ARM Neoverse V1/V2也支持SMT多线程,比例不固定
-
std::thread::hardware_concurrency()在容器或虚拟机中可能返回错误值(如QEMU未透传CPUID),应始终以OS原生接口为准 - 最易被忽略的是热插拔CPU:Linux下
/sys/devices/system/cpu/cpu*/online可能动态变化,一次快照不够,需按需重读
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











