i具有一组C 功能,可以执行一些与图像处理相关的操作。通常,我看到最终输出的时间范围为5-6ms。我正在测量使用QueryPerformanceCounter
Win32 API所花费的时间。但是,当以100张图像的连续循环中运行时,我看到某些图像的性能最高可达20ms。我的问题是如何分析此类问题。基本上,我想确定峰值是否是由于此代码延迟引起的,还是其他任务在CPU内部运行,因为此操作花费了时间。我尝试使用GetThreadTimes
API来查看我的线程在CPU中花费了多少时间,但无法根据这些数字得出结论。解决这些类型的问题的标准方法是什么?
处理过程中突然峰值背后的原因可能是IO,中断,计划的过程等。
考虑到如此低的延迟/处理时间操作,看到这样的尖峰是很常见的。IMO您可以考虑上述任何原因(可能还有更多),因此您可以考虑它们。最简单的解决方案是多次运行的,具有更多输入的实验,并将平均值用于最终考虑。
要回答有关检查/确认可以尝试的尖峰来源的问题,
- 检查图像中的变化 - 已经根据您的评论排除了
- 在处理过程中监视资源利用率。检查是否有任何资源正在窒息(%util是最简单的检查方法,而Linux上的SAR/NMON实用程序最好使用最小的开销)
- 为您的实验保留很少的CPU在系统上(CPU亲和力),该实验仅专用于您的程序,并且无需执行OS任务。任务集是最简单的尝试。更多详细信息在这里。
使用此设置运行实验并检查行为。
这是您要弄清楚的令人讨厌的事情,我什至不尝试,因为进入具体的综合很难。
通常,一个人应该运行一个许多迭代的循环(我认为100似乎太小了),然后花时间处理图像的平均时间。
将排除任何可能损害您程序表现的意外外部事件。
检查" CPU内部其他某些任务开始运行"是否会运行您的程序并标记产生该尖峰的图像的典型方法。例如,图像2、4、5和67花费太长而无法处理。再次运行您的程序,然后再次标记哪些图像产生尖峰。
如果相同的图像产生了这些尖峰,那么这不是另一个外部任务引起的。
解决这些类型的问题的标准方法是什么?
有实时操作系统(RTO)可以保证这种延迟。它与Windows或Linux完全不同。
但是,即使在通用OS上,您仍然可以做一些事情。
1。避免系统调用
一旦您要求操作系统向磁盘读取或写东西 - 无法保证延迟。因此,避免在您的关键路径上发挥任何功能:
- 甚至诸如getTimeofday()之类的函数可能会导致不可预测的延迟,因此您应该在关键时期范围内避免使用任何系统调用;
- 使用另一个线程执行IO并通过共享缓冲区传递数据到您的关键代码。
如果您的代码库很大,则诸如Linux上的strace
或Windows上的Dr Memory
等工具以跟踪系统调用。
2。避免上下文开关
Windows上的多线程是先发制人的。这意味着,有一个系统调度程序,它可能随时停止线程并安排CPU上的另一个线程。像以前一样,有rtose,可以避免这种上下文切换,但是您可以做些什么:
- 确保至少有一个CPU核心用于系统和其他任务;
- 用
SetThreadAffinityMask()
(Windows)或sched_setaffinity()
(Linux)将您的每个线程绑定到专用的CPU-这有效提示系统调度程序,以避免在此CPU上安排其他线程; - 确保硬件中断到另一个CPU;通常中断到CPU 0,因此最简单的方法是用CPU 1 ; 绑定线程
- 增加线程优先级,因此调度程序不太可能与另一个线程切换线程。
有perf
(Linux)和Intel VTune
(Windows)等工具可以确认有上下文开关。
3。避免其他非确定性特征
更多的意外延迟来源:
- 禁用交换,因此您确定您的线程内存不会在缓慢且无法预测的磁盘驱动器上交换;
- 禁用CPU涡轮增压 - 高性能CPU提升后,总会有缓慢的速度,因此CPU保持热力(TDP);
- 禁用超线程 - 从调度程序的角度来看,这些是独立的CPU,但实际上每个超线程CPU的性能取决于目前另一个线程在做什么。
希望这会有所帮助。