我在多个地方读到过Linux的默认调度程序是多核计算机上的超线程感知,这意味着如果您有一台具有两个真正内核(4HT)的机器,它不会将两个繁忙的线程安排到逻辑核上,因为它们都运行在相同的物理核上(在许多情况下,这将导致2倍的性能成本)。
但是当我在英特尔i5-2520M上运行stress -c 2 (产生两个线程在100% CPU上运行)时,通常会调度(并将两个线程保持在HT核1和2上,后者映射到相同的物理核上。即使系统是空闲的,否则。
在真正的程序中也会发生这种情况(我在这里使用stress,因为它使复制变得容易),当这种情况发生时,我的程序运行所需的时间是原来的两倍。手动设置关联与taskset修复我的程序,但我希望一个HT感知的调度程序能够正确地完成这一点。
你可以找到与egrep "processor|physical id|core id" /proc/cpuinfo | sed 's/^processor/\nprocessor/g'的HT->物理核心评估.
,所以我的问题是:为什么调度程序在这里把我的线程放在同一个物理核心上?
备注:
stress -c检查自己),并想知道原因。taskset工具或使用sched_setaffinity函数。这不是我想要的,我希望调度程序自己知道,将两个繁忙的线程映射到一个物理内核,并让一个物理内核完全空着不是一个好主意。stress特性的程序从运行在不同物理核上的好处是多么的清楚。发布于 2015-04-12 08:43:54
我想是时候从评论中总结一些知识了。
Linux知道HyperThreading --有关它的信息应该从由BIOS/UEFI提供的ACPI SRAT/SLIT表中读取--而不是由Linux构建调度器域。
域有层次结构--也就是说,在2 cpu服务器上,您将得到三层域:所有cpu、每个cpu包和每个cpu核心域。您可以从/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 systemCFS调度器的一部分是负载均衡器--应该从繁忙的核心窃取任务到另一个核心的野兽。下面是内核文档中的描述:
在执行此操作时,它将检查当前域是否已耗尽其再平衡间隔。如果是这样的话,它将在该域中运行
load_balance()。然后,它将检查父sched_domain (如果存在),以及父的父级等等。 最初,load_balance()在当前sched域中找到最繁忙的组。如果成功,它将查找该组中所有CPU的运行队列中最繁忙的运行队列。如果它设法找到这样的运行队列,它会锁定初始CPU的运行队列和新发现的最繁忙的运行队列,并开始将任务从它转移到运行队列。在此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 ...然而,负载均衡器的逻辑是复杂的,因此很难确定哪些原因可以阻止它很好地完成它的工作,以及它们与调度stop计数器之间的关系。我和那个人都不能复制你的问题。
我认为这种行为有两种可能性:
mpstat和schedstat数据)。发布于 2015-04-02 21:25:57
我无法用我的Intel(R) Xeon(R) CPU E5-1650 0@ 3.20GHz在3.13.0-48上重现这一结果。
我有6个超线程内核,逻辑核心N映射到物理核心N mod 6。
下面是top的一个典型输出,它在两列中使用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, 这是在杀死和重新启动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, 我做了几次,但没有看到在同一个物理核心上调度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, 发布于 2015-04-12 07:13:20
引用您对两个似乎正确工作的额外处理器的经验,i7-2600和XeonE5-1620;这可能是一个长远的尝试,但CPU微码更新如何?如果它是内部CPU行为,它可以包括一些可以解决问题的东西。
英特尔CPU微码下载:http://intel.ly/1aku6ak
https://stackoverflow.com/questions/29422073
复制相似问题