【问题标题】:Linux measuring time problem! std::chrono, QueryPerformanceCounter, clock_gettimeLinux测量时间问题! std::chrono、QueryPerformanceCounter、clock_gettime
【发布时间】:2020-01-05 18:25:31
【问题描述】:

我使用 Linux 中的 clock_gettime() 和 Windows 中的 QueryPerformanceCounter() 来测量时间。在测量时间的时候,我遇到了一个有趣的案例。

首先,我在无限循环中计算 DeltaTime。这个循环调用了一些更新函数。为了计算 DeltaTime,程序在 Update 函数中等待 40 毫秒,因为 update 函数是空的。

然后,在编译为 Win64-Debug 的程序中,我测量 DeltaTime。它大约是 0.040f。只要程序正在运行,这种情况就会继续(Win64-Release 也可以这样工作)。它运行正确。

但是在编译为Linux64-Debug或者Linux64-Release的程序中,出现了问题。

程序开始运行时。一切正常。 DeltaTime 约为 0.040f。但过了一会儿,deltatime 计算为 0.12XXf 或 0.132XX,紧随其后是 0.040f。以此类推。

我以为我正确使用了 QueryPerformanceCounter 并错误地使用了 clock_gettime()。然后我决定用标准库std::chrono::high_resolution_clock来试试,但是还是一样的。没有变化。

#define MICROSECONDS (1000*1000)

auto prev_time = std::chrono::high_resolution_clock::now();
decltype(prev_time) current_time;

while(1)
{
current_time = std::chrono::high_resolution_clock::now();

int64_t deltaTime = std::chrono::duration_cast<std::chrono::microseconds>(current_time - previous_time).count();

printf("DeltaTime: %f", deltaTime/(float)MICROSECONDS);

NetworkManager::instance().Update();

prev_time = current_time;

}

void NetworkManager::Update()
{
auto start = std::chrono::high_resolution_clock::now();
decltype(start) end;

while(1)
{
end = std::chrono::high_resolution_clock::now();

int64_t y = std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();

if(y/(float)MICROSECONDS >= 0.040f)
break;

}

return;

}

Normal

Problem

【问题讨论】:

  • 如果你在 strace 下运行你的 linux 可执行文件,它会显示大量的系统调用吗?
  • 考虑将MICROSECONDS 定义为float,而不是(float)MICROSECONDS。例如:constexpr float MICROSECONDS = 1000*1000;
  • int64_t y = std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(end-start).count(); 我个人会在那里使用auto 代替y。还有(float)MICROSECONDS - eeek,不要使用 C 风格的强制转换。
  • @bobah 我从未使用过 strace,但我会尝试。
  • 不相关:这些图像可以是粘贴文本。尽可能首选文字,因为图像对太多人来说是不透明的。

标签: c++ linux c++11 time-measurement


【解决方案1】:

可能的原因:

  1. 您的 clock_gettime 没有使用 VDSO,而是一个系统调用 - 如果在 strace 下运行,将可见,可以在现代内核版本上配置。
  2. 您的线程被抢占(被调度程序从 CPU 中取出)。要运行干净的实验,请以实时优先级运行您的应用并固定到特定的 CPU 内核。

另外,我会在实验时禁用 CPU 频率缩放。

【讨论】:

  • 实时优先是什么意思。它是线程优先级吗?我以前从未处理过Linux。为什么正在运行的程序会被调度程序占用 CPU。我无法理解。
  • 谢谢,我去看看。
  • @bobah 我用 "strace -p 9441 -e 'trace=!clock_gettime' -o /home/tgrl_monster_pc/strace.log" 试过了,只有一个写功能。 write(1, "DeltaTime: 0.040340 - 1567454514"..., 36) = 36. 所以肯定和调度有关。
  • clock_gettime(CLOCK_REALTIME, {1567457330, 194450552}) = 0
  • @tgrlsrt - 您可以告诉 strace 还记录特定系统调用所用的时间。如果您在 strace 输出中看到clock_gettime,这意味着在您的系统中获取时间戳可能会非常昂贵,通常您可以更改操作系统配置(具体说明取决于供应商)以使用基于 VDSO 的快速实现(请参阅this示例)。
猜你喜欢
  • 2017-08-31
  • 2014-07-16
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 2012-09-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多