Windows用GetLogicalProcessorInformation获取核心映射需两次调用,RelationProcessorCore结构的ProcessorMask标识同核逻辑处理器;Linux通过/sys/devices/system/cpu/cpu*/topology/core_id和thread_siblings_list解析拓扑;std::thread::hardware_concurrency()不可用于绑核或拓扑分析。

Windows下用 GetLogicalProcessorInformation 获取核心映射
Windows 提供了最直接的 API 来获取物理核心与逻辑处理器(超线程)的拓扑关系,GetLogicalProcessorInformation 返回一组 SYSTEM_LOGICAL_PROCESSOR_INFORMATION 结构,其中 Relationship 字段为 RelationProcessorCore 的条目就描述了一个物理核心及其绑定的逻辑处理器掩码(ProcessorMask)。
关键点:必须循环调用两次——第一次传 nullptr 获取所需缓冲区大小,第二次才真正读取数据;返回结构中每个 RelationProcessorCore 对应一个物理核心,其 ProcessorMask 是位图,第 n 位为 1 表示逻辑处理器 n 属于该核心。
- 错误常见于忽略
dwLength检查或未处理ERROR_INSUFFICIENT_BUFFER -
ProcessorMask是KAFFINITY类型(通常为ULONG_PTR),在 64 位系统上可能为 64 位宽,需用_BitScanForward或std::bitset遍历置位位 - 注意:该 API 不区分 NUMA 节点,如需跨节点信息,得配合
GetLogicalProcessorInformationEx和RelationNumaNode
Linux下解析 /sys/devices/system/cpu 目录
Linux 没有统一 syscall,但 /sys 文件系统暴露了完整的拓扑。每个逻辑 CPU(如 cpu0)下有 topology/core_id 和 topology/thread_siblings_list,前者是该逻辑核所属物理核心的 ID,后者列出同属该物理核心的所有逻辑核编号(逗号分隔,支持范围如 0-3)。
实操建议:遍历 /sys/devices/system/cpu/cpu[0-9]*/,对每个 cpuN 读取 topology/core_id,再用该值作为 key 聚合所有匹配的 cpuN;同时可读 topology/thread_siblings_list 做交叉验证。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 不是所有内核都启用
CONFIG_SCHED_MC或CONFIG_SCHED_SMT,若缺失topology/子目录,说明未暴露拓扑信息(常见于旧内核或裁剪版) -
thread_siblings_list的格式依赖内核版本,2.6.38+ 支持范围写法,旧版只写单数,需兼容解析 - 避免硬编码路径,用
glob("/sys/devices/system/cpu/cpu[0-9]*/topology/core_id", ...)更健壮
C++跨平台封装时别碰 std::thread::hardware_concurrency()
std::thread::hardware_concurrency() 只返回“推荐并发数”,既不保证是逻辑核总数,也不提供任何拓扑信息。它可能返回 0(不可靠)、被 cgroup 限制后缩水、或在某些 libstdc++ 实现中仅查 sysconf(_SC_NPROCESSORS_ONLN)(Linux)或 GetSystemInfo()->dwNumberOfProcessors(Windows),完全丢失核心映射能力。
如果你的目标是绑核(pthread_setaffinity_np / SetThreadGroupAffinity)或做 NUMA 感知调度,必须绕过这个接口,直接走系统级 API 或 sysfs。
- Clang libc++ 在 macOS 上甚至会 fallback 到
sysctlbyname("hw.ncpu"),仍无拓扑 - 即使你只想要逻辑核总数,也建议用
sysconf(_SC_NPROCESSORS_ONLN)(POSIX)或GetSystemInfo(Windows),更明确可控 - 别试图从
hardware_concurrency()推导物理核数——超线程开启时它 ≈ 2×物理核,关闭时 ≈ 物理核,但无法确认状态
映射结果常被忽略的两个细节
拿到“物理核 A → 逻辑核 {0,4}”这类映射后,容易直接用于线程绑核,但有两个现实约束常被跳过:
- 操作系统可能禁用部分逻辑核(例如 BIOS 关闭超线程、或
isolcpus=内核参数隔离了某些 CPU),此时/sys/devices/system/cpu/online或GetActiveProcessorCount(ALL_PROCESSOR_GROUPS)才是真实可用集,必须先过滤 - 现代 CPU(尤其是 AMD Zen 与 Intel hybrid 架构)存在“小核/大核”混合,
core_id或RelationProcessorCore仅表示物理封装单位,不反映性能类别;如需区分 P-core/E-core,得查/sys/devices/system/cpu/cpu*/topology/core_type(Linux)或 Windows 的GROUP_AFFINITY.Group+GetActiveProcessorGroupCount配合GetLogicalProcessorInformationEx(RelationProcessorPackage)
物理核心和逻辑核心的映射不是静态拓扑快照,而是运行时视图,受 BIOS 设置、内核启动参数、容器限制共同影响。每次初始化绑核策略前,都应重新采集并校验可用性。

















