nh2*_*nh2 18 linux performance multithreading scheduler
我已经在多个地方读过Linux的默认调度程序在多核机器上的超线程感知,这意味着如果你有一台具有2个真实内核(4 HT)的机器,它将不会以某种方式将两个忙线程安排到逻辑内核上它们都运行在相同的物理内核上(在许多情况下会导致2倍的性能成本).
但是当我stress -c 2
在我的Intel i5-2520M上运行(产生两个线程以在100%CPU上运行)时,它经常将两个线程调度(并保持)到HT核心1和2上,这些核心映射到相同的物理核心.即使系统处于空闲状态.
这也适用于真正的程序(我在stress
这里使用它因为它很容易重现),当发生这种情况时,我的程序可以理解地需要两倍的时间来运行.手动设置亲和力与taskset
我的程序的修复程序,但我希望HT感知调度程序自己正确地执行此操作.
您可以找到HT->物理核心配置egrep "processor|physical id|core id" /proc/cpuinfo | sed 's/^processor/\nprocessor/g'
.
所以我的问题是:为什么调度程序将我的线程放在同一个物理内核上?
笔记:
stress -c
),并想知道原因.taskset
工具或sched_setaffinity
函数.这不是我正在寻找的,我希望调度程序能够自己知道将两个忙线程映射到物理核心并将一个物理核心完全留空并不是一个好主意.stress
受益于在不同的物理核心上运行.我认为是时候从评论中总结一些知识了.
Linux调度程序知道超线程 - 有关它的信息应该从BIOS/UEFI提供的ACPI SRAT/SLIT表中读取 - 而不是Linux 从中构建调度程序域.
域具有层次结构 - 即在2 CPU服务器上,您将获得三层域:all-cpus,per-cpu-package和per-cpu-core域.您可以从/proc/schedstat
以下位置查看:
$ awk '/^domain/ { print $1, $2; } /^cpu/ { print $1; }' /proc/schedstat
cpu0
domain0 0000,00001001 <-- all cpus from core 0
domain1 0000,00555555 <-- all cpus from package 0
domain2 0000,00ffffff <-- all cpus in the system
Run Code Online (Sandbox Code Playgroud)
CFS调度程序的一部分是负载均衡器 - 应该将任务从繁忙的核心窃取到另一个核心的野兽.以下是来自内核文档的描述:
在执行此操作时,它会检查当前域是否已用尽其重新平衡间隔.如果是这样,它将
load_balance()
在该域上运行.然后它检查父sched_domain(如果存在)和父级的父级,依此类推.最初,
load_balance()
找到当前sched域中最繁忙的组.如果成功,它会查找该组中所有CPU的运行队列中最繁忙的运行队列.如果它设法找到这样的runqueue,它会锁定我们的初始CPU的runqueue和新发现的最繁忙的runqueue,并开始将任务从它移动到我们的runqueue.在迭代这个sched域的组时,确切的任务数量相当于先前计算的不平衡.
来自:https://www.kernel.org/doc/Documentation/scheduler/sched-domains.txt
您可以通过比较数字来监控负载均衡器的活动/proc/schedstat
.我写了一个脚本来做到这一点:schedstat.py
计数器alb_pushed
显示负载均衡器已成功移出任务:
Sun Apr 12 14:15:52 2015 cpu0 cpu1 ... cpu6 cpu7 cpu8 cpu9 cpu10 ...
.domain1.alb_count ... 1 1 1
.domain1.alb_pushed ... 1 1 1
.domain2.alb_count 1 ...
.domain2.alb_pushed 1 ...
Run Code Online (Sandbox Code Playgroud)
但是,负载均衡器的逻辑很复杂,因此很难确定哪些原因可以阻止它正常工作以及它们与schedstat计数器的关系.我和@thatotherguy都不能重现你的问题.
我看到了这种行为的两种可能性:
mpstat
和schedstat
数据)我无法使用我的Intel®Xeon®CPU E5-1650 0 @ 3.20GHz在3.13.0-48上重现此错误。
我有6个具有超线程的核心,其中逻辑核心N映射到物理核心N mod 6。
这是top
with 的典型输出,stress -c 4
分为两列,因此每一行都是一个物理核心(由于系统未处于空闲状态,我省略了几个核心):
%Cpu0 :100.0 us, %Cpu6 : 0.0 us,
%Cpu1 :100.0 us, %Cpu7 : 0.0 us,
%Cpu2 : 5.9 us, %Cpu8 : 2.0 us,
%Cpu3 :100.0 us, %Cpu9 : 5.7 us,
%Cpu4 : 3.9 us, %Cpu10 : 3.8 us,
%Cpu5 : 0.0 us, %Cpu11 :100.0 us,
Run Code Online (Sandbox Code Playgroud)
这是在杀死并重新启动之后stress
:
%Cpu0 :100.0 us, %Cpu6 : 2.6 us,
%Cpu1 :100.0 us, %Cpu7 : 0.0 us,
%Cpu2 : 0.0 us, %Cpu8 : 0.0 us,
%Cpu3 : 2.6 us, %Cpu9 : 0.0 us,
%Cpu4 : 0.0 us, %Cpu10 :100.0 us,
%Cpu5 : 2.6 us, %Cpu11 :100.0 us,
Run Code Online (Sandbox Code Playgroud)
我做了几次,没有看到在12个逻辑核心上有4个线程在同一物理核心上进行调度的任何实例。
随着-c 6
我趋向于获得这样的结果,Linux似乎正在帮助在其自身的物理内核上调度其他进程。即使这样,它们的分布也比偶然更好:
%Cpu0 : 18.2 us, %Cpu6 : 4.5 us,
%Cpu1 : 0.0 us, %Cpu7 :100.0 us,
%Cpu2 :100.0 us, %Cpu8 :100.0 us,
%Cpu3 :100.0 us, %Cpu9 : 0.0 us,
%Cpu4 :100.0 us, %Cpu10 : 0.0 us,
%Cpu5 :100.0 us, %Cpu11 : 0.0 us,
Run Code Online (Sandbox Code Playgroud)