我需要在衡量性能时防止先发制人

Do I need to prevent preemption while measuring performance

本文关键字:先发制人 性能      更新时间:2023-10-16

我想通过使用Windows中的QueryPerformanceCounter测量代码块的性能。我想知道的是,在不同的运行之间,我是否可以做一些事情来获得相同数据的相等测量(我想测量在包含POD或某些自定义对象的不同尺寸数组上的不同分类算法的性能)。我知道,由于中断或I/O操作,当前的过程可以从执行中中断。我没有做任何I/O,所以只有中断可能会影响我的测量值,我假设内核也有一些时间范围,可以运行我的过程,因此我认为这也会安排我的Proc。

人们如何通过测量执行特定代码的时间进行准确的测量?

时间测量很棘手,因为您需要找出为什么算法较慢。这取决于输入数据(例如,预分类数据请参阅为什么处理排序的数组比未分组的数组更快?)或数据集大小(适合L1,L2,L3,L3 CACHE,请参阅http://igoro.com/archive.com/archive/处理器调查效应/)。

可以极大地影响您的测量时间。同样,测量顺序可以发挥关键作用。如果您在循环中执行排序ALOG,并且它们每个分配了一些内存,则第一个测试很可能会松动。并不是因为该算法是劣等的,而是您第一次访问新分配的内存时,它将在您的流程工作集中柔软故障。释放内存后,堆分配器将返回合并的内存,该内存将具有完全不同的访问性能。如果您对更大(许多MB)数组进行排序,那将变得非常明显。

以下是第一次和第二次打印不同线程的2 GB阵列的接触时间。每页(4KB)的内存仅一次触摸一次。

Threads Size_MB Time_ms us/Page MB/s    Scenario
1       2000    355     0.693   5634    Touch 1
1       2000    11      0.021   N.a.    Touch 2
2       2000    276     0.539   7246    Touch 1
2       2000    12      0.023   N.a.    Touch 2
3       2000    274     0.535   7299    Touch 1
3       2000    13      0.025   N.a.    Touch 2
4       2000    288     0.563   6944    Touch 1
4       2000    11      0.021   N.a.    Touch 2
// Touch is from the compiler point of view a nop operation with no observable side effect 
// This is true from a pure data content point of view but performance wise there is a huge
// difference. Turn optimizations off to prevent the compiler to outsmart us.
#pragma optimize( "", off )
void Program::Touch(void *p, size_t N)
{
    char *pB = (char *)p;
    char tmp;
    for (size_t i = 0; i < N; i += 4096)
    {
        tmp = pB[i];
    }
}
#pragma optimize("", on)

为了真正判断算法的性能,不足没有完全不同的东西。

刚刚与Andrei Alexandrescu参加了Fastware的会议,他正在对这个确切的问题进行压制,如何衡量速度。显然,获得平均值是一个坏主意,但是测量很多次是一个好主意。因此,考虑到这一点,您可以测量一百万次,并记住最小的测量值,因为实际上,您会得到最少的噪音。

意味着很糟糕,因为您实际上将更多的噪声重量添加到您正在测量的实际速度中(这些不是您在评估代码速度时应该考虑的唯一事情,但这是一个很好的开始,还有更多关于代码将在何处执行的恐怖内容,以及代码在一个核心上执行并在另一个核心上执行的高架,但这是另一个故事,我认为它不适用于我的类型)。

一个好笑话是:如果您将比尔·盖茨(Bill Gates)乘公共汽车上,平均而言,那辆公共汽车中的每个人都是百万富翁:)

欢呼,并感谢所有提供输入的人。