【问题标题】:std::cout is decreasing CPU Usage?std::cout 正在减少 CPU 使用率?
【发布时间】:2019-05-09 03:50:41
【问题描述】:

我正在运行一个用 C++ 编写的程序,其中 CPU 使用率是一个重要因素,并且一直在努力降低它,直到遇到意外的异常。该程序使用std::cout 行来查看性能,当我删除它时,Windows 资源监视器中程序的 CPU 使用率会以 4-6 秒的间隔急剧上升约 1 秒。

使用std::cout 行,它可以在 0-2% 的 CPU 使用率下平稳运行,没有任何峰值。删除 std::cout 行后,它以 0-2% 的 CPU 使用率运行,在 Windows 资源监视器中,CPU 使用率每隔 4-6 秒就会飙升至 25%。

有趣的是,增加正在输出的字符串的大小会降低 CPU Spike 的高度,而减小字符串的大小会增加 CPU Spike 的高度。

以下是有问题的代码行:

float engineCompletionTime = engineTimer->getEngineCompletionTime();

/* Stops CPU from spiking */
std::cout << "Engine cycle took " << engineCompletionTime << " milliseconds." << std::endl;

if (engineCompletionTime < 14.0f) {
    std::this_thread::sleep_for(std::chrono::milliseconds((int)(14.0f - engineCompletionTime)));
}

编辑:感谢您最初的回复,但为了清楚起见:

当 std::cout 行在程序中时,没有 CPU 峰值。

当 std::cout 行不在程序中时,会出现 CPU 峰值。

随着 std::cout 打印的字符串大小增加,CPU 峰值的大小减小。

【问题讨论】:

  • std::cout是一个I/O操作,所以它需要硬件中断来通知完成,因此相对需要更长的时间。我觉得就是你说的那个尖刺。实际上,它并不占用 CPU 周期,而是 CPU 阻塞并等待直到 I/O 操作完成。
  • 尝试将std::endl 更改为'\n'。使用endl 会刷新缓冲区,如果做很多事情,比如在循环中,可能会导致 I/O 成为瓶颈。
  • Windows Resource Monitor 通常是用于衡量单个小型应用程序(在数百个可能随时唤醒的潜在 Windows 服务中运行)的 CPU 使用率的可怕工具。通常最好使用分析器来发现代码中可以进一步优化的任何区域。
  • 您通过打印引擎完成时间来打破量子叠加。尽管问题令人困惑:首先您说仅在 not 打印输出时观察到 cpu 峰值,但随后您说打印较大字符串时峰值较小。
  • 鉴于打印字符串时没有 CPU 尖峰,字符串的大小如何影响这个不存在的尖峰的大小?

标签: c++


【解决方案1】:

根据具体实现,写入std::cout 基本上涉及将控制权交给操作系统一小会儿,然后操作系统将数据发送到终端。这不是 Windows 上最快的进程,在此期间程序基本上是空闲的。 std::cout 必须处理的数据越多,延迟时间就越长,因此程序空闲的时间就越多。

如果程序花费大量时间等待输入(来自另一个程序,来自键盘或鼠标,来自“重绘屏幕”信号,如果它有 GUI,来自操作系统),那么它的 CPU 使用率很低,或来自文件系统)。基本上,CPU 使用率代表程序等待的时间部分。

如果程序的唯一工作是处理大量传入数据,并且没有延迟,那么它根本不应该等待,如果 CPU 使用率很高也可以。另一方面,如果您有一个正在等待用户输入的程序(例如一个交互式应用程序),那么 CPU 使用率很高可能会出现问题,因为这意味着该程序正在执行大量工作,即使用户没有做任何事情。

提高程序的效率通常可以解决这个问题。

CPU 使用率高的其他原因

如果您在一个紧密的循环中检查某事是否发生,而不是使用事件处理,这将导致 CPU 使用率很高,因为即使程序正在等待某事,它正在积极地检查它 .这是每三分钟检查一次门是否有包裹和等到门铃响起之间的区别。如果你每三分钟检查一次,即使你只是在等待,你也会做很多工作。但是,如果您只是等到门铃响起(与事件处理一样),您实际上并没有做任何工作。

【讨论】:

  • 您所说的在 std::cout 的空闲状态下 CPU 使用率较低的说法是有道理的,Windows 资源监控工具会将其读取为不使用 CPU,因为程序将被视为空闲在 std::cout 期间。但是,当 std::cout 不在程序中时,是什么导致 CPU 峰值?我希望如果这是问题所在,std::cout 的 CPU 峰值会更大,因为程序将被设置为空闲状态,然后是忙碌状态?这也没有解决 std::cout 输出的大小如何影响 CPU 峰值
【解决方案2】:

std::cout 并不完全是高性能的(尤其是在 Win32 上!),并且使用 std::endl 强制刷新无济于事:) 通常最好自己跟踪这些日志消息,或者:完成后写入文件,每 N 次左右打印一次 cout 的平均值,或者在最后打印一个简化的摘要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-01
    • 2015-08-02
    • 1970-01-01
    • 2013-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    相关资源
    最近更新 更多