我有一组 C++ 函数,它执行一些与图像处理相关的操作。通常我看到最终输出在 5-6ms 的时间范围内交付。我正在测量使用 QueryPerformanceCounter Win32 API 所花费的时间。但是当连续循环运行 100 张图像时,我发现某些图像的性能峰值高达 20 毫秒。我的问题是我该如何分析这些问题。基本上,我想确定峰值是否是由于此代码中的某些延迟引起的,或者是否由于此操作需要时间而在 CPU 内开始运行某些其他任务。我曾尝试使用 GetThreadTimes API 来查看我的线程在 CPU 内花费了多少时间,但无法根据这些数字得出结论。解决这些类型问题的标准方法是什么?

最佳答案


有实时操作系统 (RTOS) 可以保证这些延迟。它是与 Windows 或 Linux 完全不同的操作系统。
但是,即使在通用操作系统上,您仍然可以采取一些措施来解决延迟问题。
1. 避免系统调用
一旦您要求您的操作系统读取或写入磁盘的内容 - 就无法保证延迟。因此,请避免在关键路径上使用任何系统功能:

  • 甚至像 gettimeofday() 这样的函数也可能导致不可预测的延迟,所以你真的应该避免在时间关键的代码中进行任何系统调用;
  • 使用另一个线程来执行 IO 并通过共享缓冲区将数据传递给关键代码。

  • 如果您的代码库很大,可以使用 Linux 上的 strace 或 Windows 上的 Dr Memory 等工具来跟踪系统调用。
    2. 避免上下文切换
    Windows 上的多线程是抢占式的。这意味着,有一个系统调度程序,它可能随时停止您的线程并在您的 CPU 上调度另一个线程。和以前一样,有 RTOS 可以避免此类上下文切换,但您可以对此做一些事情:
  • 确保至少有一个 CPU 内核用于系统和其他任务;
  • 使用 SetThreadAffinityMask() (Windows) 或 sched_setaffinity() (Linux) 将您的每个线程绑定(bind)到专用 CPU——这有效地提示系统调度程序避免在该 CPU 上调度其他线程;
  • 确保硬件中断转到另一个 CPU;通常中断到 CPU 0,所以最简单的方法是将你的线程与 CPU 1+ 绑定(bind);
  • 增加您的线程优先级,因此调度程序不太可能将您的线程与另一个线程切换。

  • perf (Linux) 和 Intel VTune (Windows) 等工具来确认是否存在上下文切换。
    3. 避免其他非确定性特征
    意外延迟的更多来源:
  • 禁用交换,因此您可以确定您的线程内存不会在缓慢且不可预测的磁盘驱动器上交换;
  • 禁用 CPU turbo boost -- 高性能 CPU 提升后,总会有一个减速,因此 CPU 保持其热功率 (TDP);
  • 禁用超线程——从调度程序的角度来看,这些是独立的 CPU,但实际上每个超线程 CPU 的性能取决于当前另一个线程在做什么。

  • 希望这可以帮助。

    关于c++ - 分析性能测量中的峰值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47668372/

    10-11 23:19
    查看更多