在新的Linux内核中,上下文切换要慢得多


99

我们希望将服务器上的操作系统从Ubuntu 10.04 LTS升级到Ubuntu 12.04 LTS。不幸的是,运行已变为可运行线程的等待时间似乎从2.6内核大大增加到3.2内核。实际上,我们难以置信的延迟数字。

让我更具体地介绍一下测试。我们有一个运行两个线程的程序。第一个线程获取当前时间(使用RDTSC进行滴答),然后每秒发送一次条件变量信号。第二个线程等待条件变量,并在发出信号时唤醒。然后,它获取当前时间(使用RDTSC进行滴答)。计算第二个线程中的时间和第一个线程中的时间之间的时差,并将其显示在控制台上。此后,第二个线程再次等待条件变量。大约经过一秒钟后,第一个线程将再次发出信号。

因此,简而言之,我们每秒通过条件变量等待时间测量获得线程到线程的通信

在内核2.6.32中,此延迟约为2.8-3.5 us,这是合理的。在内核3.2.0中,此延迟已增加到40-100 us左右。我排除了两台主机之间的硬件差异。它们在相同的硬件上运行(双插槽X5687 {Westmere-EP}处理器以3.6 GHz运行,具有超线程,speedstep和所有C状态均已关闭)。测试应用程序更改了线程的亲和力,以便在同一套接字的独立物理内核上运行它们(即,第一个线程在Core 0上运行,第二个线程在Core 1上运行),因此在该线程上不会发生线程跳动核心或套接字之间的跳动/通信。

这两台主机之间的唯一区别是,一台主机运行的内核版本为2.6.32-28(快速上下文切换框),而另一台则运行最新的Ubuntu 12.04 LTS内核为3.2.0-23版本(慢上下文)。开关盒)。所有BIOS设置和硬件均相同。

内核中是否有任何变化可以解释线程调度运行需要多长时间的可笑速度减慢?

更新: 如果您想在您的主机和Linux构建上运行测试,我已将代码发布到pastebin供您阅读。编译:

g++ -O3 -o test_latency test_latency.cpp -lpthread

运行(假设您至少有一个双核计算机):

./test_latency 0 1 # Thread 1 on Core 0 and Thread 2 on Core 1

更新2:在大量搜索内核参数,发布有关内核更改和个人研究的文章之后,我已经弄清了问题所在,并发布了解决方案作为对此问题的解答。


1
只是一个猜测,但也许更改参数/proc/sys/kernel/*可能有效?如果发现有效的方法,请将该配置放入/etc/sysctl.conf文件或文件中,/etc/sysctl.d/以使其在重新启动后仍然有效。
卡洛斯·坎德罗斯

1
我比较了两个主机之间的/ proc / sys / kernel,但没有发现任何有意义的差异,尤其是在任何与调度相关的配置项目中。
Michael Goldshteyn 2012年

我隐约记得有种谣言称,RDTSC不一定在内核之间正确同步,但是我希望,如果这是一个问题,您会看到时间倒计时。您是否尝试过让亲和力在同一个内核上运行两个线程,看看会发生什么?
大卫

在Intel内核上,这个新的RDTSC可以在内核之间完美地工作,尤其是在同一CPU(即同一插槽)上的内核。有趣的是,如果两个线程都在同一个内核上运行,则在较新的内核上,延迟会降至4-10 us,而在Windows XP上,则大约为10ms。3我们在较旧的内核上。
Michael Goldshteyn's 2012年

只是一个一般性的评论-依靠TSC进行同步充其量是很困难的,尽管在您的特定情况下,由于您在一个物理芯片上使用两个内核,因此实际上应该可以解决。
twalberg 2012年

Answers:


95

解决近期内核中的不良线程唤醒性能问题的方法与从切换到intel_idlecpuidle驱动程序有关acpi_idle,该驱动程序用于较早版本的内核。可悲的是,intel_idle驱动程序会忽略用户的C状态BIOS配置,并根据自己的喜好跳动。换句话说,即使您完全禁用了PC(或服务器)BIOS中的所有C状态,该驱动程序仍将在短暂的不活动期间强制将它们打开,除非几乎所有消耗核心的综合基准(例如,压力) ) 在跑。您可以使用大多数兼容硬件上出色的Google i7z工具监视C状态转换以及与处理器频率相关的其他有用信息。

要查看您的设置中当前正在使用哪个cpuidle驱动程序,只需将current_driver文件放在以下cpuidle部分中即可/sys/devices/system/cpu

cat /sys/devices/system/cpu/cpuidle/current_driver

如果您希望现代的Linux操作系统具有尽可能短的上下文切换延迟,请添加以下内核引导参数以禁用所有这些节能功能:

在Ubuntu 12.04上,您可以通过将它们添加到中的GRUB_CMDLINE_LINUX_DEFAULT条目中/etc/default/grub然后运行来执行此操作update-grub。要添加的引导参数为:

intel_idle.max_cstate=0 processor.max_cstate=0 idle=poll

以下是有关这三个引导选项的详细信息:

设置intel_idle.max_cstate为零将(或acpi_idle至少根据该选项的文档)将cpuidle驱动程序还原为,或将其完全禁用。在我的盒子上,它完全被禁用(即,显示中的current_driver文件/sys/devices/system/cpu/cpuidle会产生的输出none)。在这种情况下,processor.max_cstate=0不需要第二个引导选项。但是,文档指出将intel_idle驱动程序的max_cstate设置为零应该将OS还原为acpi_idle驱动程序。因此,为防万一,我放入了第二个引导选项。

processor.max_cstate选项将acpi_idle驱动程序的最大C状态设置为零,并希望将其禁用。我没有可以对其进行测试的系统,因为intel_idle.max_cstate=0完全淘汰了我可用的所有硬件上的cpuidle驱动程序。但是,如果您的安装确实仅使用第一个引导选项将您从还原intel_idleacpi_idle,请告诉我第二个选项是否processor.max_cstate按照注释中的说明进行操作,以便我可以更新此答案。

最后,这三个参数中的最后一个 idle=poll是真正的力量猪。它将禁用C1 / C1E,C1 / C1E将消除最后的延迟,但会消耗更多的功率,因此仅在确实需要时才使用它。对于大多数人来说,这将是多余的,因为C1 *延迟并不是那么大。使用我在原始问题中描述的硬件上运行的测试应用程序,延迟从9 us变为3 us。对于高度延迟敏感的应用程序(例如,金融交易,高精度遥测/跟踪,高频率数据采集等),这无疑是一个显着的降低,但是对于大多数人而言,所造成的电力损失可能不值得桌面应用程序。唯一可以确定的方法是分析应用程序在性能与性能方面的改进。

更新:

经过对各种idle=*参数的附加测试之后,我发现将设置idlemwait硬件是否支持是一个更好的主意。看来,使用MWAIT/MONITOR指令可以使CPU进入C1E,而不会在线程唤醒时间中增加任何明显的延迟。使用idle=mwait,您将获得更低的CPU温度(与相比idle=poll),更少的功耗并仍保留轮询空闲循环的出色的低延迟。因此,基于这些发现,我针对低CPU线程唤醒延迟而更新的推荐引导参数集是:

intel_idle.max_cstate=0 processor.max_cstate=0 idle=mwait

使用idle=mwait代替idle=poll可能还有助于启动Turbo Boost(通过帮助CPU保持在其TDP [Thermal Design Power]以下)和超线程(对于这种情况,MWAIT是在不消耗整个物理核心的情况下的理想机制)时间避免更高的C状态)。但是,这仍将在测试中得到证明,我将继续这样做。

更新2:

mwait空闲选项已经从较新的3.x的内核去掉(感谢用户ck_进行更新)。剩下两个选择:

idle=halt-应该和一样工作mwait,但是请进行测试以确保您的硬件是这种情况。该HLT指令几乎等同于MWAIT状态提示为0 的指令。问题在于,需要中断才能退出HLT状态,而可以使用存储器写(或中断)退出MWAIT状态。根据Linux内核在其空闲循环中使用的功能,这可以使MWAIT潜在地更有效。所以,正如我所说的测试/配置文件,看看它是否满足您的延迟需求...

idle=poll -最高性能的选择,但要消耗功率和热量。


抱歉,为什么您期望C状态由固件管理?挂起状态是运行时状态,它们由操作系统按设计进行管理。如您所知,如果您不希望运行时挂起,请不要使用它。
安迪·罗斯

6
抱歉,但是C状态,EIST和C1E可以在BIOS中关闭。我希望操作系统尊重我的BIOS设置。考虑到在这种情况下的可怕工具和文档,尤其如此。
Michael Goldshteyn

4
可能是通过您的BIOS关闭了。我不知道相关规范中有什么要求。抱歉,但是“期待” BIOS中的任何内容都会一再咬你。固件在现代PC中所能做的最好的事情就是什么。对不起,您很惊讶,但是坦率地说,这是用户错误。您的基准测试是衡量暂停和恢复时间。
安迪·罗斯

19
BIOS功能选择的作用之一是启用/禁用设备。在某些情况下,这些选择会在操作系统(例如,主板上的USB,eSATA和NIC)上强制执行。在其他情况下,期望操作系统尊重您的意愿(例如,EIST,C状态,超线程,禁用执行,AES-NI,虚拟化等)。BIOS提供了一个独立于OS的中央设备/功能选择界面。这使用户可以在主机上安装全部使用相同硬件功能的多个(也许相差很大)操作系统。但是,此答案是主观的,因此必须同意不同意。
Michael Goldshteyn 2012年

1
最近的3.x内核lkml.org/lkml/2013/2/10/21不再支持idle = mwait 。
ck_14年

8

也许变慢的是futex,它是条件变量的构建块。这将阐明一些内容:

strace -r ./test_latency 0 1 &> test_latency_strace & sleep 8 && killall test_latency

然后

for i in futex nanosleep rt_sig;do echo $i;grep $i test_latency_strace | sort -rn;done

它将显示有趣的系统调用所花费的微秒,按时间排序。

在内核2.6.32上

$ for i in futex nanosleep rt_sig;do echo $i;grep $i test_latency_strace | sort -rn;done
futex
 1.000140 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000129 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000124 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000119 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000106 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000103 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000102 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 0.000125 futex(0x7f98ce4c0b88, FUTEX_WAKE_PRIVATE, 2147483647) = 0
 0.000042 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000038 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000037 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000030 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000029 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 0
 0.000028 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000027 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000018 futex(0x7fff82f0ec3c, FUTEX_WAKE_PRIVATE, 1) = 0
nanosleep
 0.000027 nanosleep({1, 0}, {1, 0}) = 0
 0.000019 nanosleep({1, 0}, {1, 0}) = 0
 0.000019 nanosleep({1, 0}, {1, 0}) = 0
 0.000018 nanosleep({1, 0}, {1, 0}) = 0
 0.000018 nanosleep({1, 0}, {1, 0}) = 0
 0.000018 nanosleep({1, 0}, {1, 0}) = 0
 0.000018 nanosleep({1, 0}, 0x7fff82f0eb40) = ? ERESTART_RESTARTBLOCK (To be restarted)
 0.000017 nanosleep({1, 0}, {1, 0}) = 0
rt_sig
 0.000045 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000040 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000038 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000034 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000033 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000032 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000032 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000031 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000031 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000028 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000028 rt_sigaction(SIGRT_1, {0x37f8c052b0, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x37f8c0e4c0}, NULL, 8) = 0
 0.000027 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000027 rt_sigaction(SIGRTMIN, {0x37f8c05370, [], SA_RESTORER|SA_SIGINFO, 0x37f8c0e4c0}, NULL, 8) = 0
 0.000027 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000025 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000025 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000023 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000023 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000022 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
 0.000022 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000021 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000021 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000021 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000021 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000021 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000019 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0

在内核3.1.9上

$ for i in futex nanosleep rt_sig;do echo $i;grep $i test_latency_strace | sort -rn;done
futex
 1.000129 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000126 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000122 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000115 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000114 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000112 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000109 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 0.000139 futex(0x3f8b8f2fb0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
 0.000043 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000041 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000037 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000036 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000034 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000034 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
nanosleep
 0.000025 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000022 nanosleep({1, 0}, {0, 3925413}) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
 0.000021 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
rt_sig
 0.000045 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000044 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000043 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000040 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000038 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000037 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000036 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000036 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000035 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000034 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000031 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000027 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000027 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000027 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000027 rt_sigaction(SIGRT_1, {0x3f892067b0, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x3f8920f500}, NULL, 8) = 0
 0.000026 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000026 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000025 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000024 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000023 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
 0.000023 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000022 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000021 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000019 rt_sigaction(SIGRTMIN, {0x3f89206720, [], SA_RESTORER|SA_SIGINFO, 0x3f8920f500}, NULL, 8) = 0

我发现此具有5年历史的错误报告包含一个“乒乓”性能测试,该测试将

  1. 单线程libpthread互斥体
  2. libpthread条件变量
  3. 普通的旧Unix信号

我必须添加

#include <stdint.h>

为了进行编译,我使用此命令

g++ -O3 -o condvar-perf condvar-perf.cpp -lpthread -lrt

在内核2.6.32上

$ ./condvar-perf 1000000
NPTL
mutex                 elapsed:    29085 us; per iteration:   29 ns / 9.4e-05 context switches.
c.v. ping-pong test   elapsed:  4771993 us; per iteration: 4771 ns / 4.03 context switches.
signal ping-pong test elapsed:  8685423 us; per iteration: 8685 ns / 4.05 context switches.

在内核3.1.9上

$ ./condvar-perf 1000000
NPTL
mutex                 elapsed:    26811 us; per iteration:   26 ns / 8e-06 context switches.
c.v. ping-pong test   elapsed: 10930794 us; per iteration: 10930 ns / 4.01 context switches.
signal ping-pong test elapsed: 10949670 us; per iteration: 10949 ns / 4.01 context switches.

我得出的结论是,内核2.6.32和3.1.9之间的上下文切换确实放慢了速度,尽管没有您在内核3.2中观察到的那么快。我知道这还不能回答您的问题,我会继续研究。

编辑:我发现更改进程(两个线程)的实时优先级可以提高3.1.9的性能以匹配2.6.32。但是,在2.6.32上设置相同的优先级会使它变慢。

现在是我的结果:

在内核2.6.32上

$ ./condvar-perf 1000000
NPTL
mutex                 elapsed:    29629 us; per iteration:   29 ns / 0.000418 context switches.
c.v. ping-pong test   elapsed:  6225637 us; per iteration: 6225 ns / 4.1 context switches.
signal ping-pong test elapsed:  5602248 us; per iteration: 5602 ns / 4.09 context switches.
$ chrt -f 1 ./condvar-perf 1000000
NPTL
mutex                 elapsed:    29049 us; per iteration:   29 ns / 0.000407 context switches.
c.v. ping-pong test   elapsed: 16131360 us; per iteration: 16131 ns / 4.29 context switches.
signal ping-pong test elapsed: 11817819 us; per iteration: 11817 ns / 4.16 context switches.
$ 

在内核3.1.9上

$ ./condvar-perf 1000000
NPTL
mutex                 elapsed:    26830 us; per iteration:   26 ns / 5.7e-05 context switches.
c.v. ping-pong test   elapsed: 12812788 us; per iteration: 12812 ns / 4.01 context switches.
signal ping-pong test elapsed: 13126865 us; per iteration: 13126 ns / 4.01 context switches.
$ chrt -f 1 ./condvar-perf 1000000
NPTL
mutex                 elapsed:    27025 us; per iteration:   27 ns / 3.7e-05 context switches.
c.v. ping-pong test   elapsed:  5099885 us; per iteration: 5099 ns / 4 context switches.
signal ping-pong test elapsed:  5508227 us; per iteration: 5508 ns / 4 context switches.
$ 

我在Fedora和CentOS上运行它,没有Ubuntu。我将发布结果。
2012年

好的,我在两个主机(即不同的内核)上都运行了它,结果几乎没有差异。因此,该测试没有突出显示任何差异。futex的调用时间在小数点后第四位不同-性能的显着降低。等等,整数是秒吗?我刚刚看到您发布了结果,它们看起来与我的相似...
Michael Goldshteyn 2012年

好的,这排除了futex的实现-我们回到您的上下文切换理论....随意删除此答案,因为它确实属于注释...我只是想要格式化命令的功能。
2012年

是的,时间以秒为单位...持续时间超过一秒的futex调用用于等待条件的线程。
2012年

那么,如果从结果中搜集到什么呢?
Michael Goldshteyn 2012年

1

由于pstate驱动程序与c状态分开,因此您可能还会看到处理器在较新的进程和Linux内核中单击向下。因此,要禁用此功能,请使用以下内核参数:

intel_pstate=disable

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.