随手记——SMP系统中亲和性获取和设置
Posted 穿越临界点
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了随手记——SMP系统中亲和性获取和设置相关的知识,希望对你有一定的参考价值。
在学习资料满天飞的大环境下,知识变得非常零散,体系化的知识并不多,这就导致很多人每天都努力学习到感动自己,最终却收效甚微,甚至放弃学习。我的使命就是过滤掉大量的无效信息,将知识体系化,以短平快的方式直达问题本质,把大家从大海捞针的痛苦中解脱出来。
1 什么是亲和性
亲和性简单理解就是某一个线程或中断和哪个处理器核亲近。和哪个(一个或多个)核亲近,就在占用哪个核的资源,除非这个核被关闭了。
系统默认的亲和性就是对所有核无差别对待,一个线程可以负载分担到任何核上。
2 为什么要设置亲和性
系统默认的所有线程和中断的亲和性是会根据负载,均匀分担到各个核上的。所以,会存在经常动态调整绑核关系的情况。因为核迁移过程是需要时间的,也会影响Cache命中率,经常进行核迁移会影响系统性能。
系统的使用者由于对业务比较熟悉,所以可以选择将指定的线程绑定在指定的处理器核心上,以提高系统的效率和稳定性。此外,定位问题也比较直观一些。
3 设置线程亲和性
3.1 在shell中设置亲和性
在shell中设置亲和性的指令是 taskset 。该指令可以将指定线程迁移到指定的CPU核心(簇)上。
# 设置亲和性
指令名称 选项 CPU核心列表 线程ID
taskset -pc 0,1-3,5 PID
# 获取亲和性
taskset -p PID
3.2 在C语言中设置亲和性
在C语言中设置亲和性的接口有3组,如下表所示。
接口 | 功能 | 说明 |
---|---|---|
int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); | 设置进程或线程(轻量级进程)亲和性 | pid填0就是本进程;pid填syscall(SYS_gettid)就是轻量级进程。 |
int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); | 获取进程或线程(轻量级进程)亲和性 | 同上 |
int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset); | 设置线程亲和性 | 和上述接口对比主要是第一个入参类型不同。 |
int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset); | 获取线程亲和性 | 同上 |
int pthread_attr_setaffinity_np(pthread_attr_t *attr, size_t cpusetsize, const cpu_set_t *cpuset); | 设置线程亲和性 | 用在创建线程之前,和上述接口的主要区别也是第一个参数。 |
int pthread_attr_getaffinity_np(pthread_attr_t *attr, size_t cpusetsize, cpu_set_t *cpuset); | 获取线程亲和性 | 同上 |
下面,只对第一组接口给出使用示例。其他接口的用法大同小异,遇到之后查询一下man手册就可以了。
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <sched.h>
5 #include <sys/syscall.h>
6
7
8 /* Get thread affinity */
9 int get_thread_affinity()
10 {
11 pid_t tid;
12 cpu_set_t mask;
13 int cpu_num = 0;
14 int i = 0;
15
16 tid = syscall(SYS_gettid); //or use syscall(__NR_gettid)
17 CPU_ZERO(&mask);
18
19 if (sched_getaffinity(tid, sizeof(cpu_set_t), &mask)) {
20 perror("");
21 return -1;
22 }
23 cpu_num = sysconf(_SC_NPROCESSORS_CONF);
24 for (i = 0; i < cpu_num; i++) {
25 if (CPU_ISSET(i, &mask))
26 printf("The %d cpu is set.\\n", i);
27 }
28
29 return 0;
30 }
31 /* Set thread affinity */
32 int set_thread_affinity(int cpu_no)
33 {
34 pid_t tid;
35 cpu_set_t mask;
36
37 tid = syscall(SYS_gettid);
38 CPU_ZERO(&mask);
39 CPU_SET(cpu_no, &mask);
40
41 if (sched_setaffinity(tid, sizeof(cpu_set_t), &mask)) {
42 perror("");
43 return -1;
44 }
45
46 return 0;
47 }
48
49 int main(int argc, char* argv[])
50 {
51 (void)get_thread_affinity();
52 (void)set_thread_affinity(3);
53 printf("------------------after set affinity---------------------\\n");
54 (void)get_thread_affinity();
55
56
57 return 0;
58 }
4 设置中断的亲和性
设置和获取中断亲和性可以借助proc系统。设置就是往文件中写,获取直接读取文件即可。
# 例如将中断号8的亲和性设置为第0-3个核上
# 掩码形式
echo f > /proc/irq/8/smp_affinity
# 列表形式
echo 0-3 > /proc/irq/8/smp_affinity_list
恭喜你又坚持看完了一篇博客,又进步了一点点!如果感觉还不错就点个赞再走吧,你的点赞和关注将是我持续输出的哒哒哒动力~~
以上是关于随手记——SMP系统中亲和性获取和设置的主要内容,如果未能解决你的问题,请参考以下文章