mat*_*tch 4 c++ linux multithreading scheduler
刚刚测试了两个小程序,
#include <thread>
int main()
{
for (int i = 0; i < 10000000; i++)
{
std::this_thread::yield();
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
和:
#include <thread>
#include <chrono>
int main()
{
using namespace std::literals;
for (int i = 0; i < 10000000; i++)
{
std::this_thread::sleep_for(0s);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在我的系统上得到了各自的计时(Ubuntu 22.04 LTS,内核版本 5.19.0-43-generic),
./a.out 0,33s user 1,36s system 99% cpu 1,687 total
Run Code Online (Sandbox Code Playgroud)
和:
./a.out 0,14s user 0,00s system 99% cpu 0,148 total
Run Code Online (Sandbox Code Playgroud)
为什么std::this_thread::yield()比 慢 10 倍std::this_thread::sleep_for(0s)?
注意 g++ 和 clang++ 之间的计时类似。
编辑:正如答案中所指出的,这是 STL 实现的优化,调用sleep(0)实际上慢了 300 倍(50us vs 150ns)。
快速浏览一下源代码this_thread::sleep_for
template<typename _Rep, typename _Period>
inline void
sleep_for(const chrono::duration<_Rep, _Period>& __rtime)
{
if (__rtime <= __rtime.zero())
return;
...
Run Code Online (Sandbox Code Playgroud)
所以sleep_for(0s)什么也不做,事实上你的测试程序使用了0.0s的系统时间,基本上是一个完全在用户空间运行的空循环(事实上我怀疑如果你使用优化进行编译,它将被完全删除)
另一方面,yield调用* sched_yield又将schedule()在内核空间中调用,因此至少执行一些逻辑来检查是否有另一个线程需要调度。
我相信你的 0.33s 用户空间时间基本上是系统调用开销。
*实际上跳转到__libcpp_thread_yieldthen 调用的地方sched_yield,至少在 Linux 上是这样