【问题标题】:Cost of context switch between threads of same process, on LinuxLinux上同一进程的线程之间的上下文切换成本
【发布时间】:2011-08-22 23:16:47
【问题描述】:

是否有任何关于 Linux 上同一进程的线程之间上下文切换成本的良好经验数据(主要是 x86 和 x86_64)?我说的是一个线程在自愿或非自愿进入睡眠之前在用户空间中执行的最后一条指令与同一进程的不同线程在同一 cpu/核心上唤醒后执行的第一条指令之间的周期数或纳秒数.

我编写了一个快速测试程序,它在分配给同一个 cpu/core 的 2 个线程中不断地执行rdtsc,将结果存储在一个 volatile 变量中,并与它的姊妹线程的相应 volatile 变量进行比较。当它第一次检测到姊妹线程的值发生变化时,它会打印出差异,然后返回循环。我在 Atom D510 cpu 上以这种方式获得了大约 8900/9600 个周期的最小/中值计数。这个程序是否合理,数字是否可信?

我的目标是估计在现代系统上,每个连接线程的服务器模型是否可以与选择类型的多路复用竞争甚至优于选择类型的多路复用。这在理论上似乎是合理的,因为从在 fd X 上执行 IO 到 fd Y 的转换仅涉及在一个线程中休眠并在另一个线程中唤醒,而不是多个系统调用,但这取决于上下文切换的开销.

【问题讨论】:

  • 无论如何,你到底有没有做过任何基准测试?如果是,结果如何?

标签: c linux pthreads posix context-switch


【解决方案1】:

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

首先,您得到的数字听起来肯定是在合理范围内。但是请注意,实现相同 ISA 的不同 CPU 模型之间的中断/陷阱延迟可能会有很大差异。如果您的线程使用了浮点或向量操作,这也是另一回事,因为如果没有,内核会避免保存/恢复浮点或向量单元状态。

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

如果您的目标是为每个连接的线程建模服务器,那么您可能不应该测量非自愿上下文切换延迟 - 通常在这样的服务器中,大多数上下文切换将是自愿的,因为 @ 中的线程阻塞987654323@ 正在等待来自网络的更多数据。因此,更好的测试平台可能需要测量从 read() 中的一个线程阻塞到另一个线程从同一线程中唤醒的延迟。

请注意,在一个编写良好且负载较重的多路复用服务器中,从 fd X 到 fd Y 的转换通常会涉及相同的单个系统调用(因为服务器会遍历从单个epoll())。一个线程也应该比多个线程拥有更少的缓存占用空间,只需通过只有一个堆栈即可。我怀疑解决问题的唯一方法(对于“解决”的某些定义)可能是进行基准枪战......

【讨论】:

  • 除非你的连接是长期存在的,否则在 epoll 集中添加/删除 fds 的额外系统调用的成本几乎肯定会超过任何好处,所以我宁愿忽略它并假设一个传统的选择/投票。我同意基准点球大战会很有趣,但我希望获得一些初步数据,以了解在将面向性能的线程 httpd 或其他东西组合在一起之前,我是否可以期望“获胜”。 :-)
  • 顺便说一句,您关于自愿与非自愿的观点非常好。我可能会调整测试以简单地在线程之间放置一个管道并测量写入和读取之间的时间......
  • 哇,通过自愿切换,延迟降至约 4900 个周期。相比之下,来自管道的read 通常需要大约 2000 个周期。我认为每连接一个线程的服务器可能会获胜,这听起来似乎是合理的。
  • @R.:啊,是的,当然。尽管如此,poll()epoll() 中的哪一个是最佳的取决于问题的确切参数 - 例如活动文件描述符与总文件描述符之间的典型比率(以及连接的寿命,正如您所指出的) )。
  • 这就是为什么这个问题被标记为 C。:-)
猜你喜欢
  • 2011-07-23
  • 2017-09-09
  • 2011-07-27
  • 2019-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多