您的位置:首页 >CPU亲和性掩码位运算解析
发布于2026-02-26 阅读(0)
扫一扫,手机访问

本文详解 getproccount 函数如何通过系统调用获取 CPU 亲和性掩码,并利用经典位操作(Brian Kernighan 变体 + 并行位计数)在常数时间内统计掩码中置位比特数,从而准确推导物理/逻辑核心数量。
本文详解 getproccount 函数如何通过系统调用获取 CPU 亲和性掩码,并利用经典位操作(Brian Kernighan 变体 + 并行位计数)在常数时间内统计掩码中置位比特数,从而准确推导物理/逻辑核心数量。
getproccount 是 Go 语言早期运行时(pre-1.4)中用于探测当前进程可调度 CPU 核心数量的关键函数。其核心逻辑分为三步:获取亲和性掩码 → 解析掩码数组 → 统计所有掩码字中置位(bit set)总数。最终返回值即为操作系统允许该进程使用的逻辑核心数;若系统调用失败或掩码全零,则保守返回 1。
int32 r = runtime·sched_getaffinity(0, sizeof(buf), buf);
该系统调用将当前进程的 CPU 亲和性掩码(affinity mask)写入 buf 数组。buf 类型为 uintptr[16],在 64 位系统中每个元素为 8 字节(64 位),因此最多可容纳 16 × 64 = 1024 个 CPU 核心的掩码信息。r 返回实际写入的字节数,故有效数组长度为 r / sizeof(uintptr)。
对 buf[i] 中的每个 uintptr 值 t,采用经典的 SWAR(SIMD Within A Register)位计数算法,仅用 3 行位运算即可在 O(1) 时间内算出其二进制表示中 1 的个数:
t = t - ((t >> 1) & 0x5555555555555555ULL); // Step 1: 每2位一组,计算组内1的个数(0~2) t = (t & 0x3333333333333333ULL) + ((t >> 2) & 0x3333333333333333ULL); // Step 2: 每4位一组,累加(0~4) cnt += (int32)((((t + (t >> 4)) & 0xF0F0F0F0F0F0F0FULL) * 0x101010101010101ULL) >> 56); // Step 3: 全局求和(0~64)
算法原理简述:
✅ 该算法无需分支、无查表、全流水,是编译器内置 __builtin_popcount 的底层实现逻辑之一,在无硬件 POPCNT 指令的老平台(如部分 ARM 或早期 x86)上尤为关键。
return cnt ? cnt : 1;
若 sched_getaffinity 调用失败(r ≤ 0)或所有掩码字均为 0(cnt == 0),函数返回 1。这是一种安全降级策略:确保程序至少能在单核上运行,避免因探测失败导致不可用。
掌握此类底层位操作,不仅有助于理解运行时设计哲学,更是构建高性能系统软件(如调度器、内存分配器)的必备基础能力。
下一篇:WPS转Word方法详解
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9