3

我正在寻找一个简单的操作/例程,如果连续重复可能会“浪费”时间。

我正在研究 gprof 如何配置应用程序,因此这种“浪费时间”需要在用户空间中浪费时间,并且不应该需要外部库。IE,调用 sleep(20) 将“浪费” 20 秒的时间,但 gprof 不会记录这个时间,因为它发生在另一个库中。

对于可以重复浪费时间的简单任务有什么建议吗?

4

4 回答 4

6

Tomalak 解决方案的另一个变体是设置警报,因此在您的忙等待循环中,您不需要继续发出系统调用,而只需检查信号是否已发送。

于 2011-08-18T10:05:44.907 回答
6

在不产生 CPU 的情况下“浪费”时间的最简单方法是紧密循环。

如果您不需要限制浪费的持续时间(例如,您可以通过在完成后简单地终止进程来控制它),然后使用 C 风格*

for (;;) {}

(但请注意,该标准允许实现假设程序最终会终止,所以从技术上讲,这个循环 - 至少在 C++0x 中 - 具有未定义的行为并且可以被优化!**

否则,您可以手动计时:

time_t s = time(0);
while (time(0) - s < 20) {}

或者,如果在 GNU 兼容的系统上,您可以使用“警报”来结束循环,而不是重复发出time系统调用(这将导致在内核中花费一些时间) :signal.h

alarm(20);
while (true) {}

在"Handler Returns"的文档页面上甚至还有一个非常相似的示例。

(当然,这些方法都会让你在中间时间达到 100% 的 CPU,并让毛茸茸的独角兽从你的耳朵里掉出来。)


*为了清楚起见,故意使用{}尾随而不是;故意使用。归根结底,在这样的上下文中写分号是没有任何借口的;这是一个可怕的习惯,当你在“真实”代码中使用它时,它会成为一个维护陷阱。

** 见[n3290: 1.10/2][n3290: 1.10/24]

于 2011-08-18T10:02:46.720 回答
0

一个简单的循环就可以了。如果您正在研究 gprof 的工作原理,我假设您已经缓慢而仔细地阅读了这篇论文。我还假设您熟悉这些问题

于 2011-08-18T13:03:31.650 回答
0

这是一个繁忙的循环,它在现代硬件上每次迭代运行一个周期,至少clanggcc可能任何具有至少一些优化标志的合理编译器编译:

void busy_loop(uint64_t iters) {
    volatile int sink;
    do {
        sink = 0;
    } while (--iters > 0);
    (void)sink;
}

这个想法只是存储到volatile sink每次迭代。这可以防止循环被优化掉,并使每次迭代都有可预测的工作量(至少一个存储)。现代硬件每个周期可以做一次存储,而循环开销一般可以在同一个周期内并行完成,因此通常实现每次迭代一个周期。iters因此,您可以通过除以您的 CPU 速度(以 GHz为单位)来计算给定数量的挂钟时间(以纳秒为单位)。例如,一个 3 GHz CPU 大约需要 2 秒(20 亿纳秒)才能达到busy_loop.iters == 6,000,000,000

于 2017-08-07T22:03:13.050 回答