0%

周谈(47)- cpu亲和性设置

前言

最近在测试程序的性能,发现测试出来的数据波动比较大,不是很稳定。

测试的机器上存在大小核的区别,系统在空闲的时候尽量会使用小核进行运算,这样就可以降低功耗。

正常一个程序在运行的时候,也是会在不同的cpu之间进行切换的。通过设置了CPU亲和性后,测试出来的数据就基本变化不大了。

CPU亲和性

相关概念

CPU亲和性就是绑定某一进程(或线程)到特定的CPU(或CPU集合),从而使得该进程(或线程)只能运行在绑定的CPU(或CPU集合)上。CPU亲和性利用了这样一个事实:进程上一次运行后的残余信息会保留在CPU的状态中(也就是指CPU的缓存)。如果下一次仍然将该进程调度到同一个CPU上,就能避免缓存未命中等对CPU处理性能不利的情况,从而使得进程的运行更加高效。

这样使用者可以根据机器对不同的CPU进行功能划分,根据自己的策略来利用好CPU。

CPU核

我们可以通过命令查看当前系统的核数,实际使用的核数目。

1
2
3
4
5
6

cat /proc/cpuinfo | grep processor | wc -l
或者
lscpu
或者
nproc

nproc

如果是写代码,那么C语言也有函数可以获取CPU数目。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 内核
pr_info("Cpu count %d", NR_CPUS);

//用户态
#include <unistd.h>
int sysconf(_SC_NPROCESSORS_CONF);/* 返回系统可以使用的核数,但是其值会包括系统中禁用的核的数目,因此该值并不代表当前系统中可用的核数 */
int sysconf(_SC_NPROCESSORS_ONLN);/* 返回值真正的代表了系统当前可用的核数 */

/* 以下两个函数与上述类似 */
#include <sys/sysinfo.h>
int get_nprocs_conf (void);/* 可用核数 */
int get_nprocs (void);/* 真正的反映了当前可用核数 */

CPU亲和性设置

对于已经存在的程序,我们也可以使用taskset这个命令来限制程序运行的CPU。

1
2
3
taskset -c 3 <program_cmd> # 设置程序在0和1两个CPU上运行 
taskset -p <pid> # 查看对应进程的CPU亲和性, 输出的实际是个16进制值, 每一位代表一个cpu, 该位为1 表示进程会在该CPU上运行

自己编写代码的话,可以通过CPU_SET设置,C语言的话就是调用相应的API接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*设置或者获取进程的CPU亲和性*/
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <sched.h>

int sched_setaffinity(pid_t pid, size_t cpusetsize,
const cpu_set_t *mask);

int sched_getaffinity(pid_t pid, size_t cpusetsize,
cpu_set_t *mask);


/*设置或者获取线程的CPU亲和性*/

#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <pthread.h>

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);

// Compile and link with -pthread.

对于内核态的线程kthread也有对应的接口设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 如果是启动的内核线程的话 kthread , include/linux/kthread.h
// 可以创建到指定的cpu上
struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data),
void *data,
unsigned int cpu,
const char *namefmt);
// 也可以在创建后,指定运行cpu
static inline struct task_struct *
kthread_run_on_cpu(int (*threadfn)(void *data), void *data,
unsigned int cpu, const char *namefmt)
{
struct task_struct *p;

p = kthread_create_on_cpu(threadfn, data, cpu, namefmt);
if (!IS_ERR(p))
wake_up_process(p);

return p;
}

更多

这段时间比较忙,渐渐进入了一个技术leader的角色,每天都过得很快。

除了自己一部分的任务外,还得把控团队的代码质量,进行代码检视,指导刚毕业的同事,优化实现逻辑,处理外部需求,跟踪同事的任务进度。

每天的时间感觉都不够用了,一天天一周周的过去了,同时落了很多篇周谈。

还有就是下班后,回到家里,就没有了一个人那时候的学习的氛围了,家里有小孩的话,没有安静的氛围了,经常被打断。

总之,这个写博客文章的习惯还是值得继续坚持的,大家一起共勉!


行动,才不会被动!

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。

博客地址: https://fishmwei.github.io

掘金主页: https://juejin.cn/user/2084329776486919


Powered By Valine
v1.5.2