taskset可绑定进程到指定cpu核心,但默认仅作用于主线程;多线程程序需加-a参数或手动设置各线程亲和性,否则子线程仍自由调度。

taskset 能直接绑定进程到指定 CPU 核心,但默认只作用于主线程,多线程程序必须加 -a 或手动处理每个线程,否则子线程仍自由调度。
查进程当前绑了哪些 CPU 核心
别只看 taskset -p PID 输出的十六进制掩码(比如 0xff),容易误判。更直观的是用 -c 参数:
-
taskset -cp PID直接显示类似0-3,6,8-10:2的可读列表 - 多线程程序中,
taskset -p PID只查主线程(TID == PID);其他线程需先用ps -T -p PID列出所有 TID,再逐个执行taskset -p TID - 若返回
Operation not permitted,说明目标进程启用了cap_sys_nice或你非 root 且无权修改该进程
启动时就绑定,别等进程跑起来再改
运行中用 taskset -pc 修改亲和性,只能影响后续调度,无法重置已加载的缓存、TLB 或 NUMA 内存页位置——这对性能敏感服务是硬伤。
Linux AI 服务器 — 将 Linux 服务器转换为本地 AI 推理集群。使用 systemd、NVIDIA CUDA 实现无头 Linux AI,零 GUI 开销。
- 正确写法:
taskset -c 1,3-4 ./myapp --arg value(-c后紧跟 CPU 列表,再跟完整命令) - 错误写法:
taskset -c 1,3-4 --arg value ./myapp(--arg被当成taskset自己的参数,报错) - 多线程程序务必加
-a:taskset -ac 0,2 python workload.py,否则仅主线程受约束,新 fork 的线程仍按系统默认策略调度
运行中动态绑定已有进程
对已启动但未绑定的进程,可用 taskset -p 强制重设,但要注意权限与时机:
- 普通用户只能改自己启动的进程;改系统进程或他人进程需 root 权限
- 若进程正处在内核态长时间执行(如大块 I/O 或锁等待),
taskset -p可能短暂失败,重试即可 - 等效写法:用十进制编号列表
taskset -c 0,2 1234和十六进制掩码taskset -p 0x5 1234(0x5 = 0101₂,对应 CPU 0 和 CPU 2)效果一致 - 验证是否生效:持续运行
ps -eo pid,psr,comm | grep myapp,观察psr列是否稳定在预期核心号上
为什么 top 里看到进程还在跳核?
这不是 taskset 失效,而是你误解了“绑定”的含义:它设置的是**允许运行的 CPU 集合**,不是“永远钉死某一个核”。
- 只要亲和性掩码含多个 CPU(如
-c 2,3),内核就会在其中做负载均衡——这是正常行为 - 想彻底固定到单核,掩码必须只含一位:
taskset -c 2或taskset 0x4(CPU 2 对应 2² = 4) - 真正要隔离关键服务,得结合
systemd的CPUAffinity=持久化配置,或在代码中用pthread_setaffinity_np()控制每个工作线程
最常被忽略的一点:CPU 编号不等于物理核序号。超线程下,CPU 0 和 CPU 1 很可能属于同一物理核,共享 L1/L2 缓存;NUMA 架构中,不同节点的内存访问延迟差异巨大。绑定前务必先运行 lscpu 或 numactl --hardware 看清拓扑,否则优化可能适得其反。










