分析性能测量中的峰值
Analyzing spikes in performance measurement
我有一组 C++ 函数可以执行一些与图像处理相关的操作。通常我看到最终输出在 5-6 毫秒的时间范围内交付。我正在测量使用 QueryPerformanceCounter
Win32 API 所花费的时间。但是,当 运行 在包含 100 张图像的连续循环中时,我发现某些图像的性能峰值高达 20 毫秒。我的问题是我如何着手分析这些问题。基本上,我想确定尖峰是由于此代码中的某些延迟引起的,还是由于此操作花费了时间而在 CPU 内启动了 运行 的某些其他任务。我尝试使用 GetThreadTimes
API 来查看我的线程在 CPU 中花费了多少时间,但无法根据这些数字得出结论。解决此类问题的标准方法是什么?
你试图弄清楚的事情很糟糕,我什至不会尝试,因为很难得出具体的结论。
一般来说,应该 运行 一个 多次 迭代的循环(我认为 100 似乎太小了),然后取一张图像的平均时间被处理。
这将排除任何可能损害程序性能的意外外部事件。
检查 "some other task started running inside the CPU" 是否会出现的典型方法是 运行 您的程序一次并标记产生该尖峰的图像。例如,图像 2、4、5 和 67 处理时间太长。 运行 重复你的程序几次,并再次标记哪些图像产生尖峰。
如果相同的图像产生这些尖峰,则它不是由其他外部任务引起的。
处理过程中突然出现峰值的原因可能是 IO、中断、计划进程等
考虑到如此低的 latency/processing 时间操作,看到这样的尖峰是很常见的。由于上述任何原因(可能还有更多),您可以在 IMO 中考虑它们。最简单的解决方案是 运行 多次输入更多的相同实验,并取平均值作为最终考虑。
要回答有关 checking/confirming 峰值来源的问题,您可以尝试以下操作,
- 检查图像中的变化 - 已根据您的评论排除
- 监控处理过程中的资源利用率。检查是否有任何资源阻塞(%util 是最简单的检查方法,linux 上的 SAR/NMON 实用程序最好,开销最小)
- 在系统(CPU 亲和力)上为您的实验预留几个 CPU,它们专用于您的程序,没有 OS 任务 运行 . Taskset 是最容易试用的实用程序。更多详细信息 here。
运行 使用此设置进行实验并检查行为。
What is the standard way to go about troubleshooting these types of issues?
有实时操作系统 (RTOS) 可以保证这种延迟。 class 操作系统与 Windows 或 Linux 完全不同。
但是,即使是一般用途,您仍然可以采取一些措施来解决延迟 OS。
1。避免系统调用
一旦您要求 OS 向磁盘读取或写入内容 - 无法保证延迟。因此,避免在关键路径上使用任何系统功能:
- 即使像 gettimeofday() 这样的函数也可能会导致不可预测的延迟,因此您应该真正避免在时间关键代码中进行任何系统调用;
- 使用另一个线程执行 IO 并通过共享缓冲区将数据传递给您的关键代码。
如果您的代码库很大,可以使用 Linux 上的 strace
或 Windows 上的 Dr Memory
等工具来跟踪系统调用。
2。避免上下文切换
Windows 上的多线程是抢占式的。这意味着,有一个系统调度程序,它可能会随时停止您的线程并在您的 CPU 上调度另一个线程。和以前一样,有 RTOSes,可以避免这种上下文切换,但是您可以做一些事情:
- 确保至少有一个 CPU 内核用于系统和其他任务;
- 将您的每个线程绑定到专用的 CPU 和
SetThreadAffinityMask()
(Windows) 或 sched_setaffinity()
(Linux) -- 这有效地提示系统调度程序以避免在此 CPU; 上调度其他线程
- 确保硬件中断转到另一个CPU;通常中断会转到 CPU 0,所以最简单的方法是将线程与 CPU 1+;
绑定
- 增加你的线程优先级,这样调度程序就不太可能用另一个线程切换你的线程。
有 perf
(Linux) 和 Intel VTune
(Windows) 等工具来确认上下文切换。
3。避免其他非确定性特征
意外延误的更多来源:
- 禁用交换,这样您就可以确定您的线程内存不会在缓慢且不可预测的磁盘驱动器上交换;
- 禁用 CPU 涡轮增压——在高性能 CPU 增压后,总会减速,因此 CPU 保持其热功率 (TDP);
- 禁用超线程——从调度程序的角度来看,它们是独立的 CPU,但实际上每个超线程的性能 CPU 取决于另一个线程此刻正在做什么。
希望对您有所帮助。
我有一组 C++ 函数可以执行一些与图像处理相关的操作。通常我看到最终输出在 5-6 毫秒的时间范围内交付。我正在测量使用 QueryPerformanceCounter
Win32 API 所花费的时间。但是,当 运行 在包含 100 张图像的连续循环中时,我发现某些图像的性能峰值高达 20 毫秒。我的问题是我如何着手分析这些问题。基本上,我想确定尖峰是由于此代码中的某些延迟引起的,还是由于此操作花费了时间而在 CPU 内启动了 运行 的某些其他任务。我尝试使用 GetThreadTimes
API 来查看我的线程在 CPU 中花费了多少时间,但无法根据这些数字得出结论。解决此类问题的标准方法是什么?
你试图弄清楚的事情很糟糕,我什至不会尝试,因为很难得出具体的结论。
一般来说,应该 运行 一个 多次 迭代的循环(我认为 100 似乎太小了),然后取一张图像的平均时间被处理。
这将排除任何可能损害程序性能的意外外部事件。
检查 "some other task started running inside the CPU" 是否会出现的典型方法是 运行 您的程序一次并标记产生该尖峰的图像。例如,图像 2、4、5 和 67 处理时间太长。 运行 重复你的程序几次,并再次标记哪些图像产生尖峰。
如果相同的图像产生这些尖峰,则它不是由其他外部任务引起的。
处理过程中突然出现峰值的原因可能是 IO、中断、计划进程等
考虑到如此低的 latency/processing 时间操作,看到这样的尖峰是很常见的。由于上述任何原因(可能还有更多),您可以在 IMO 中考虑它们。最简单的解决方案是 运行 多次输入更多的相同实验,并取平均值作为最终考虑。
要回答有关 checking/confirming 峰值来源的问题,您可以尝试以下操作,
- 检查图像中的变化 - 已根据您的评论排除
- 监控处理过程中的资源利用率。检查是否有任何资源阻塞(%util 是最简单的检查方法,linux 上的 SAR/NMON 实用程序最好,开销最小)
- 在系统(CPU 亲和力)上为您的实验预留几个 CPU,它们专用于您的程序,没有 OS 任务 运行 . Taskset 是最容易试用的实用程序。更多详细信息 here。
运行 使用此设置进行实验并检查行为。
What is the standard way to go about troubleshooting these types of issues?
有实时操作系统 (RTOS) 可以保证这种延迟。 class 操作系统与 Windows 或 Linux 完全不同。
但是,即使是一般用途,您仍然可以采取一些措施来解决延迟 OS。
1。避免系统调用
一旦您要求 OS 向磁盘读取或写入内容 - 无法保证延迟。因此,避免在关键路径上使用任何系统功能:
- 即使像 gettimeofday() 这样的函数也可能会导致不可预测的延迟,因此您应该真正避免在时间关键代码中进行任何系统调用;
- 使用另一个线程执行 IO 并通过共享缓冲区将数据传递给您的关键代码。
如果您的代码库很大,可以使用 Linux 上的 strace
或 Windows 上的 Dr Memory
等工具来跟踪系统调用。
2。避免上下文切换
Windows 上的多线程是抢占式的。这意味着,有一个系统调度程序,它可能会随时停止您的线程并在您的 CPU 上调度另一个线程。和以前一样,有 RTOSes,可以避免这种上下文切换,但是您可以做一些事情:
- 确保至少有一个 CPU 内核用于系统和其他任务;
- 将您的每个线程绑定到专用的 CPU 和
SetThreadAffinityMask()
(Windows) 或sched_setaffinity()
(Linux) -- 这有效地提示系统调度程序以避免在此 CPU; 上调度其他线程
- 确保硬件中断转到另一个CPU;通常中断会转到 CPU 0,所以最简单的方法是将线程与 CPU 1+; 绑定
- 增加你的线程优先级,这样调度程序就不太可能用另一个线程切换你的线程。
有 perf
(Linux) 和 Intel VTune
(Windows) 等工具来确认上下文切换。
3。避免其他非确定性特征
意外延误的更多来源:
- 禁用交换,这样您就可以确定您的线程内存不会在缓慢且不可预测的磁盘驱动器上交换;
- 禁用 CPU 涡轮增压——在高性能 CPU 增压后,总会减速,因此 CPU 保持其热功率 (TDP);
- 禁用超线程——从调度程序的角度来看,它们是独立的 CPU,但实际上每个超线程的性能 CPU 取决于另一个线程此刻正在做什么。
希望对您有所帮助。