多核编程与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亲和力的主要内容,如果未能解决你的问题,请参考以下文章

多线程利用多核,cpu利用率却达不到100%?

OpenStack中的CPU绑核、NUMA亲和、大页内存

Linux 操作系统原理 — NUMA 架构中的多线程调度开销与性能优化

怎样才能找出哪个 CPU 内核正在运行该进程?

Linux 有问必答:如何知道进程运行在哪个 CPU 内核上?

如何在 C++ 程序中通过拓扑考虑在多核 HT 上实现亲和性?