在Linux上,在相同进程的线程之间切换上下文的开销

在Linux(x86和x86_64,主要是感兴趣的)上,同一进程的线程之间的上下文切换的成本是否有任何良好的经验数据? 我说的是在一个线程在用户空间中执行的最后一个指令之间的周期数或纳秒数,在自动地或非自愿地进入睡眠之前,并且第一个指令在同一个cpu / core上唤醒之后执行的同一进程的不同线程。

我写了一个快速的testing程序,它不断rdtsc在分配给同一个cpu / core的2个线程中执行rdtsc ,将结果存储在一个volatilevariables中,并与其姐妹线程的相应volatilevariables进行比较。 它第一次检测到姐妹线程的值发生变化,就会打印出差异,然后返回循环。 在Atom D510 CPU上,我得到的最低/中位数约为8900/9600。 这个程序看起来是否合理,数字是否可信?

我的目标是估计在现代系统中,每个连接线程的服务器模型是否可以与select型多路复用相比具有竞争性,甚至可以超越select型多路复用。 这在理论上似乎是合理的,因为从fd X执行IO到fd Y的过渡只涉及在一个线程中睡眠,而在另一个线程中唤醒,而不是多个系统调用,但是这取决于上下文切换的开销。

(免责声明:这不是问题的直接答案,只是一些建议,我希望会有所帮助)。

首先,你得到的数字当然听起来像是在球场内。 但是请注意,执行相同ISA的不同CPU模型之间的中断/陷阱延迟可能会有很大差异。 如果您的线程使用了浮点或向量操作,那么这也是一个不同的故事,因为如果它们没有内核,则避免保存/恢复浮点或向量单元状态。

通过使用内核跟踪基础架构,您应该能够获得更准确的数据 – 特别是性能测试旨在衡量和分析调度程序的延迟。

如果你的目标是模拟每个连接线程的服务器,那么你可能不应该测量非自愿的上下文切换延迟 – 通常在这样一个服务器上,大部分上下文切换将是自愿的,因为一个线程阻塞在read()等待从网络获取更多数据。 因此,一个更好的测试平台可能涉及到测量read()中的一个线程阻塞到另一个线程从同一个线程中被唤醒的延迟。

请注意,在一个编写良好的多任务服务器负载较重的情况下,从fd X到fd Y的转换通常会涉及同一个系统调用(因为服务器遍历从单个epoll()返回的活动文件描述符列表)。 一个线程应该比多线程的缓存占用更少,只需要一个堆栈即可。 我怀疑解决这个问题的唯一方法(对于“解决”的定义)可能是基准枪战。