cpu绑定技术解析

什么是 Linux 内核硬亲和性(affinity)?

在 Linux 内核中,所有的进程都有一个相关的数据结构,称为 task_struct。这个结构非常重要,原因有很多;其中与 亲和性(affinity)相关度最高的是 cpus_allowed 位掩码。这个位掩码由 n 位组成,与系统中的 n 个逻辑处理器一一对应。 具有 4 个物理 CPU 的系统可以有 4 位。如果这些 CPU 都启用了超线程,那么这个系统就有一个 8 位的位掩码。

如果为给定的进程设置了给定的位,那么这个进程就可以在相关的 CPU 上运行。因此,如果一个进程可以在任何 CPU 上运行,并且能够根据需要在处理器之间进行迁移,那么位掩码就全是 1。实际上,这就是 Linux 中进程的缺省状态。

Linux 内核 API 提供了一些方法,让用户可以修改位掩码或查看当前的位掩码:

sched_set_affinity() (用来修改位掩码)
sched_get_affinity() (用来查看当前的位掩码)
注意,cpu_affinity 会被传递给子线程,因此应该适当地调用 sched_set_affinity

测试cpu绑定

我们使用nginx进程进行测试

准备测试进程

首先找到nginx的进程pid和当前分配的cpu id(psr) cpu,这里可以看到nginx worker的进程现在运行在3 cpu上

1
2
3
$ ps -eLo ruser,pid,lwp,psr,cmd | grep -v grep |grep nginx
root 30406 30406 2 nginx: master process ./sbin/nginx
nobody 31778 31778 3 nginx: worker process

使用taskset绑定cpu

1
2
3
taskset -pc 0 31778
pid 31778's current affinity list: 0-3
pid 31778's new affinity list: 0

结果

通过ab工具发起大量测试请求

1
ab -c 10 -n 1000000 http://localhost/index

使用watch的方式持续监控看到nginx worker一直运行于0 cpu

1
2
3
4
$ watch "ps -eLo ruser,pid,lwp,psr,cmd | grep -v grep |grep 31778"
Every 2.0s: ps -eLo ruser,pid,lwp,psr,cmd | grep -v grep |grep 31778 Sun Jun 21 16:09:21 2020
nobody 31778 31778 0 nginx: worker process

相关文档: https://www.ibm.com/developerworks/cn/linux/l-affinity.html

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器