Sté*_*ane 12 g++ thread-sleep c++11
如果我并排放两个电话来确定最小的可测量持续时间:
// g++ -std=c++11 -O3 -Wall test.cpp
#include <chrono>
typedef std::chrono::high_resolution_clock hrc;
hrc::time_point start = hrc::now();
hrc::time_point end = hrc::now();
std::chrono::nanoseconds duration = end - start;
std::cout << "duration: " << duration.count() << " ns" << std::endl;
Run Code Online (Sandbox Code Playgroud)
我已经在循环中运行了数千次,并且在我特定的3.40GHz桌面上我一直得到40 ns +/- 2 ns.
但是,当我想看看我能睡到的最短时间时:
#include <thread>
hrc::time_point start = hrc::now();
std::this_thread::sleep_for( std::chrono::nanoseconds(1) );
hrc::time_point end = hrc::now();
std::chrono::nanoseconds duration = end - start;
std::cout << "slept for: " << duration.count() << " ns" << std::endl;
Run Code Online (Sandbox Code Playgroud)
这告诉我,我平均睡眠55400纳秒,或55.4微秒.远远超过我的预期.
把上面的代码放到for()
循环中,我试着睡不同的数量,这就是结果:
我有一些问题:
Jon*_*ely 13
有什么可以解释这些数字?
有一个非常明显的模式,你的所有结果都比你要求睡觉的时间长54000ns.如果你看看GCC this_thread::sleep_for()
是如何在GNU/Linux上实现的,你会看到它只是使用nanospleep
而且正如Cubbi的评论所说,调用该函数可能需要大约50000ns.我猜一些成本就是进行系统调用,因此从用户空间切换到内核并返回.
为什么在负时间内睡眠会返回200+ ns,而睡眠时间为0+纳秒会导致50,000+纳秒?
猜测我会说C库会检查负数并且不会进行系统调用.
负数作为睡眠时间是记录/支持的功能,还是我不小心偶然发现了一些我不能依赖的奇怪错误?
标准不禁止传递否定参数,因此允许它,并且函数应该"立即"返回,因为相对超时指定的时间已经过去了.你不能依赖负参数返回比非负参数更快,这是你特定实现的一个人工制品.
是否有更好的C++睡眠调用可以让我更加一致/可预测的睡眠时间?
我不这么认为 - 如果我知道一个,那么我们将在GCC中使用它来实现this_thread::sleep_for()
.
编辑:在更新版本的GCC的libstdc ++中我添加了:
if (__rtime <= __rtime.zero())
return;
Run Code Online (Sandbox Code Playgroud)
因此,当请求零或负持续时间时,将不会有系统调用.
受到Straight Fasttimer_slack_ns
\xe2\x80\x99s 答案的启发,我评估了和 的效果SCHED_FIFO
。因为timer_slack_ns
你必须添加
#include <sys/prctl.h> // prctl\n\xe2\x8b\xae\nprctl (PR_SET_TIMERSLACK, 10000U, 0, 0, 0);\n
Run Code Online (Sandbox Code Playgroud)\n\n这意味着对于当前进程,计时器裕量应设置为 10\xc2\xb5s,而不是默认值 50\xc2\xb5s。其效果是响应能力更好,但能耗稍高。该进程仍然可以由非特权用户运行。要更改调度程序策略,SCHED_FIDO
您必须是\xe2\x80\x9croot\xe2\x80\x9d。所需的代码是
#include <unistd.h> // getpid\n#include <sched.h> // sched_setscheduler\n\xe2\x8b\xae\n const pid_t pid {getpid ()};\n struct sched_param sp = {.sched_priority = 90};\n if (sched_setscheduler (pid, SCHED_FIFO, &sp) == -1) {\n perror ("sched_setscheduler");\n return 1;\n }\n
Run Code Online (Sandbox Code Playgroud)\n\n我在带有 GUI 的桌面系统上运行St\xc3\xa9phane \xe2\x80\x99s 代码片段(Debian 9.11,内核 \n4.9.189-3+deb9u2,g++ 9.2 -O3,Intel\xc2\xae Core\xe2\x84 \xa2 i5-3470T CPU @ 2.90GHz)。第一种情况的结果(后续时间测量)是
\n\n由于中间没有系统调用,延迟约为260ns,受进程设置影响不大。对于正态分布时序,图表是直线,横坐标值为 0.5,纵坐标值为平均值,斜率代表标准偏差。测量值与测量值的不同之处在于存在较高延迟的异常值。
\n\n与此相反,第二种情况(休眠一纳秒)在进程设置之间有所不同,因为它包含系统调用。因为睡眠时间太少了,睡觉并不会增加任何时间。因此,图表仅显示开销:
\n\n正如St\xc3\xa9phane所说,开销默认约为 64\xc2\xb5s (这里 \xe2\x80\x99s 有点大。)。通过将 降低到 10\xc2\xb5s,时间可以减少到大约 22 timer_slack_ns
\xc2\xb5s。并通过调用特权 sched_setscheduler()
,开销可以减少到大约 12\xc2\xb5s。但如图所示,即使在这种情况下,延迟也可能超过 50\xc2\xb5s(在 0.0001% 的运行中)。
测量结果显示了开销与流程设置的基本依赖性。其他测量结果表明,非 GUI XEON 服务器系统上的波动要低一个数量级以上。
\n 归档时间: |
|
查看次数: |
11144 次 |
最近记录: |