跳转到主内容
极星编程网:以代码为星,赴技术山海!

golang怎么绑cp

runtime.NumCPU()返回逻辑CPU数,非物理核数,直接用作coreID易越界报EINVAL;绑定需先LockOSThread再调SchedSetaffinity,否则因goroutine迁移而失效。
runtime.NumCPU()
返回的是逻辑 CPU 数量,不是物理核心数,更不等于可用绑定目标——直接用它当
coreID
传给
syscall.SchedSetaffinity
很可能越界报
EINVAL
。真要绑 CPU,得先确认系统实际拓扑,再按需锁定 OS 线程 + 设置亲和性,否则绑定无效或反拖慢性能。 为什么 goroutine 直接调
syscall.SchedSetaffinity
没用 Go 的 goroutine 是用户态协程,调度器随时可能把它从当前 M(OS 线程)上换走,换到另一个 M 上运行。而
syscall.SchedSetaffinity
绑定的是**当前 OS 线程**,不是 goroutine。所以: 必须先调
runtime.LockOSThread()
,把当前 goroutine 和它正在跑的 OS 线程锁死 再立刻调
syscall.SchedSetaffinity(0, &cpuSet)
(
0
表示当前线程) 如果中途没锁住、或锁住后又 unlock 了,绑定就失效 常见错误:在
go func() { ... }()
里直接绑,没锁线程,绑的其实是启动 goroutine 的那个临时 M,极不稳定
coreID
超出范围就 panic?看清楚
runtime.NumCPU()
的含义
runtime.NumCPU()
返回的是
sysconf(_SC_NPROCESSORS_ONLN)
的值,即当前在线的逻辑 CPU 数(含超线程)。但它不反映: CPU 是否被内核隔离(如
isolcpus=
启动参数屏蔽的核) NUMA 节点分布(比如 48 核机器,但
numactl -H
显示是 2×24,跨节点绑核会触发远端内存访问) 容器或 cgroup 限制(
cpuset.cpus
可能只暴露 0-3,但
NumCPU()
还返回 48) 安全做法是:先读
/sys/devices/system/cpu/online
或用
numactl --show
确认可用 core 列表,再选其中某个 ID;别硬套
NumCPU()-1
。 立即学习 “ go语言免费学习笔记(深入) ”; go语言参考手册 中文CHM版 Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译 下载 绑完 CPU,QPS 反而掉了一半?检查这几个点 盲目绑定最常导致性能倒退,尤其在压测场景: client 和 server 都绑了同一颗核(比如都绑
0
),实际变成串行竞争,不是隔离 网络密集型服务绑单核后,netpoller 和 timer goroutine 被卡住,导致 accept 延迟飙升 没配
numactl --membind
,绑在 node1 的核却访问 node0 的内存,延迟翻倍 用
debug.SetMaxThreads(1)
限制 M 数,又绑死线程,一旦 goroutine 进 syscal 就阻塞整个 M,新请求进不来 压测前建议:用
perf record -e sched:sched_migrate_task
看 task 是否真没迁移;用
go tool trace
看 G 是否长期处于
Syscall
或
Runnable
状态。 真正需要 CPU 绑定的场景极少——通常是低延迟交易、实时音视频编码、或与硬件设备直通的驱动层程序。多数 Web 服务靠 Go 自身调度器就够了;硬绑反而破坏 runtime 对 M/P/G 的动态平衡。如果非绑不可,优先用
numactl
启动整个进程,比在代码里 syscall 更稳。

相关文章