2017-07-28 61 views
5

通过查看/proc/<PID>/sched调度统计,你可以得到一个输出这样的:Linux - 迁移和交换机之间的区别?

[[email protected] ~]$ cat /proc/1/sched 
systemd (1, #threads: 1) 
------------------------------------------------------------------- 
se.exec_start        : 2499611106.982616 
se.vruntime         :   7952.917943 
se.sum_exec_runtime       :   58651.279127 
se.nr_migrations        :    53355 
nr_switches         :    169561 
nr_voluntary_switches      :    168185 
nr_involuntary_switches      :     1376 
se.load.weight        :    1048576 
se.avg.load_sum        :    343837 
se.avg.util_sum        :    338827 
se.avg.load_avg        :     7 
se.avg.util_avg        :     7 
se.avg.last_update_time      :  2499611106982616 
policy          :     0 
prio           :     120 
clock-delta         :     180 
mm->numa_scan_seq       :     1 
numa_pages_migrated       :     296 
numa_preferred_nid       :     0 
total_numa_faults       :     34 
current_node=0, numa_group_id=0 
numa_faults node=0 task_private=0 task_shared=23 group_private=0 group_shared=0 
numa_faults node=1 task_private=0 task_shared=0 group_private=0 group_shared=0 
numa_faults node=2 task_private=0 task_shared=0 group_private=0 group_shared=0 
numa_faults node=3 task_private=0 task_shared=11 group_private=0 group_shared=0 
numa_faults node=4 task_private=0 task_shared=0 group_private=0 group_shared=0 
numa_faults node=5 task_private=0 task_shared=0 group_private=0 group_shared=0 
numa_faults node=6 task_private=0 task_shared=0 group_private=0 group_shared=0 
numa_faults node=7 task_private=0 task_shared=0 group_private=0 group_shared=0 

我一直在试图找出一些应对herehere迁移和交换机之间的差异。总结这些响应:

  • nr_switches:上下文切换的数量。
  • nr_voluntary_switches:自动开关的数量,即线程被阻塞,因此另一个线程被拾取。
  • nr_involuntary_switches:由于还有一个饥饿的线程已准备好运行,调度程序将线程踢出。

因此,什么是migrations?这些概念是否相关?迁移是核心之间的核心和交换机之间的交换?

回答

7

迁移是当一个线程(通常在上下文切换之后)在不同于预定时间的CPU上安排的。

编辑1

这里是维基百科上有关迁移的详细信息: https://en.wikipedia.org/wiki/Process_migration

这里是内核代码增加计数器: https://github.com/torvalds/linux/blob/master/kernel/sched/core.c#L1175

if (task_cpu(p) != new_cpu) { 
    ... 
    p->se.nr_migrations++; 

EDIT 2

一个线程可以迁移到另一个CPU在下列情况下:

  1. exec()
  2. fork()
  3. 在线程唤醒。
  4. 如果线程关联掩码已更改。
  5. 当前CPU变为脱机状态时。

欲了解更多信息,请看看功能set_task_cpu()move_queued_task()migrate_tasks()相同的源文件中:https://github.com/torvalds/linux/blob/master/kernel/sched/core.c

的政策调度如下在select_task_rq(),这取决于类调度的描述您在使用。该policier的基本版本:

if (p->nr_cpus_allowed > 1) 
    cpu = p->sched_class->select_task_rq(p, cpu, sd_flags, wake_flags); 
else 
    cpu = cpumask_any(&p->cpus_allowed); 

来源:https://github.com/torvalds/linux/blob/master/kernel/sched/core.c#L1534

所以为了避免迁移,设置使用sched_setaffinity(2)系统调用对应的POSIX API pthread_setaffinity_np(3)你的线程CPU关联掩码。

这里是select_task_rq的)的完全公平调度器的定义(: https://github.com/torvalds/linux/blob/master/kernel/sched/fair.c#L5860

的逻辑是相当复杂的,但基本上,我们要么选择兄弟空闲CPU或者找一个最空闲的新的。

希望这回答你的问题。

+0

你说“通常”,那么调度程序要迁移到另一个核心的策略是什么?你有什么资料可以证实吗? – horro

+0

它依赖于调度程序,优先级,亲和性等。基本上,如果没有CPU关联性并且以前的CPU正忙于另一个任务,则该线程会在另一个CPU上进行调度。我还用一些链接更新了答案。 –

+1

@horro在尝试手动控制线程核心关联性之后,认为没有意义,策略过于深入。有太多的东西需要考虑,每台电脑都不一样。例如,在双CPU机器上,您可以考虑哪个CPU拥有大部分线程数据(QPI总线没有超载问题)。这本身就是一个复杂的问题;连续的内存页面可以在CPU之间交错,或者不是(这是某些机器上的BIOS设置)。操作系统知道所有这些以及更多。我害怕撬得太深... – bazza