分析绩效评估的高峰

时间:2017-12-06 06:43:38

标签: c++ performance performance-testing benchmarking

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

3 个答案:

答案 0 :(得分:3)

处理过程中突然出现峰值的原因可能是IO,中断,预定进程等等。

考虑到这种低延迟/处理时间操作,这种尖峰很常见。 IMO你可以考虑他们因为上述任何原因(可能会有更多)。最简单的解决方案是使用多次输入进行相同的实验,并将平均值作为最终考虑因素。

要回答有关检查/确认尖峰来源的问题,您可以尝试按照

进行操作
  1. 检查图像的变化 - 已根据您的评论排除
  2. 在处理期间监控资源利用率。检查是否有任何资源窒息(%util是最简单的检查方式,并且linux上的SAR / NMON实用程序最好以最小的开销)
  3. 为您的实验预留几个系统CPU(CPU Affinity),这些CPU专用于您的程序,并且不会对它们运行任何操作系统任务。 Taskset是最简单的实用工具。更多细节是here
  4. 使用此设置运行实验并检查行为。

答案 1 :(得分:2)

这是你想要弄清楚的一件令人讨厌的事情,我甚至不会尝试,因为进入具体的妄想是很难的。

一般情况下,应该运行许多迭代的循环(我认为100只看起来太小),然后花费处理图像的平均时间。

这将排除任何可能影响程序性能的意外外部事件。

检查“其他任务是否开始在CPU内部运行”的典型方法是运行程序一次并标记产生该峰值的图像。例如,图像2,4,5和67需要很长时间才能处理。再次运行程序,再次标记哪些图像产生峰值。

如果相同的图像产生这些尖峰,那么它不是由另一个外部任务引起的。

答案 2 :(得分:1)

  

解决这些类型问题的标准方法是什么?

有实时操作系统(RTOS)可以保证这种延迟。它与Windows或Linux完全不同,是一类操作系统。

但是,即使在通用操作系统上,您仍然可以做一些关于延迟的事情。

1。避免系统调用

一旦你要求你的操作系统读取或写入磁盘的东西 - 无法保证延迟。因此,请避免关键路径上的任何系统功能:

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

如果您的代码库很大,那么Linux上的strace或Windows上的Dr Memory等工具可以跟踪系统调用。

2。避免上下文切换

Windows上的多线程是先发制人的。这意味着,有一个系统调度程序,可以随时停止您的线程并在您的CPU上安排另一个线程。和以前一样,有一些RTOS可以避免这种上下文切换,但你可以做些什么:

  • 确保至少有一个CPU核心用于系统和其他任务;
  • 将每个线程绑定到具有SetThreadAffinityMask()(Windows)或sched_setaffinity()(Linux)的专用CPU - 这有效地提示系统调度程序,以避免在此CPU上调度其他线程;
  • 确保硬件中断进入另一个CPU;通常中断转到CPU 0,所以最简单的方法是将你的线程绑定到CPU 1 +;
  • 增加您的线程优先级,因此调度程序不太可能将您的线程切换到另一个。

perf(Linux)和Intel VTune(Windows)等工具可以确认是否存在上下文切换。

3。避免使用其他非确定性功能

更多意外延迟的来源:

  • 禁用交换,因此您确定您的线程内存不会在缓慢且不可预测的磁盘驱动器上交换;
  • 禁用CPU turbo boost - 在高性能CPU提升后,总会有一个减速,因此CPU保持其热功率(TDP);
  • 禁用超线程 - 从调度程序的角度来看,这些是独立的CPU,但实际上每个超线程CPU的性能取决于另一个线程目前正在做什么。

希望这有帮助。