多核编程与CPU亲和力
Posted 程序猿Ricky的日常干货
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多核编程与CPU亲和力相关的知识,希望对你有一定的参考价值。
多核编程
多核编程和多线程编程还是有一些差异的,对于多线程编程,我们可以创建多个线程去处理业务,但是不会关心具体哪个进程运行在哪个CPU上,而多核的意思则是可以把特定任务绑定到特定的CPU上运行。这样的好处是什么?能够把重要的任务独立到一个CPU上运行,从而不受其他任务影响,提升该任务的响应速度。通过CPU绑定也能提升cache命中率,从而提高性能。具体到使用上,就是利用如下API绑定CPU:
int sched_setaffinity(pid_t pid, size_t cpusetsize,
cpu_set_t *mask);
int sched_getaffinity(pid_t pid, size_t cpusetsize,
cpu_set_t *mask);
内核实现
long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
......
cpuset_cpus_allowed(p, cpus_allowed);
cpumask_and(new_mask, in_mask, cpus_allowed);
retval = set_cpus_allowed_ptr(p, new_mask);
......
这个函数中有关键的3个步骤,取出当前task进程中的cpus_allowed bitmap mask,然后通过cpumask_and与in_mask进行位与操作,最后把cpuset mask设置到对应的task进程结构体中set_cpus_allowed_ptr,这个函数的目的就是把pid对应进程绑定到in_mask中指定的cpu上运行。下面看一下cpus_allowed是在哪里生效的:
static inline
int select_task_rq(struct task_struct *p, int cpu, int sd_flags, int wake_flags)
if (p->nr_cpus_allowed > 1)
cpu = p->sched_class->select_task_rq(p, cpu, sd_flags, wake_flags);
/*
* In order not to call set_task_cpu() on a blocking task we need
* to rely on ttwu() to place the task on a valid ->cpus_allowed
* cpu.
*
* Since this is common to all placement strategies, this lives here.
*
* [ this allows ->select_task() to simply return task_cpu(p) and
* not worry about this generic constraint ]
*/
if (unlikely(!cpumask_test_cpu(cpu, tsk_cpus_allowed(p)) ||
!cpu_online(cpu)))
cpu = select_fallback_rq(task_cpu(p), p);
return cpu;
这里当进程wakeup或者fork时,内核会执行到select_task_rq函数,该函数中会对cpus_allowed进行检测,对于当前进程不允许的cpu,会对该进程重新选择runqueue,把当前进程放到允许运行的cpu runqueue上:
if (unlikely(!cpumask_test_cpu(cpu, tsk_cpus_allowed(p)) ||
!cpu_online(cpu)))
cpu = select_fallback_rq(task_cpu(p), p);
以上是关于多核编程与CPU亲和力的主要内容,如果未能解决你的问题,请参考以下文章
Linux 操作系统原理 — NUMA 架构中的多线程调度开销与性能优化