8

我发现了一个衡量函数性能的好问题,答案建议使用 Stopwatch 如下

Stopwatch sw = new Stopwatch();
sw.Start();
//DoWork
sw.Stop();
//take sw.Elapsed

但是,如果您在多处理器机器下运行,这是否有效?线程可以切换到另一个处理器,可以吗?同样的事情也应该在 Enviroment.TickCount 中。如果答案是肯定的,我应该将我的代码包装在 BeginThreadAffinity 中,如下所示

Thread.BeginThreadAffinity();
Stopwatch sw = new Stopwatch();
sw.Start();
//DoWork
sw.Stop();
//take sw.Elapsed
Thread.EndThreadAffinity();

附言

切换可以发生在线程级别,而不仅仅是处理器级别,例如,如果函数在另一个线程中运行,那么系统可以将其切换到另一个处理器,如果发生这种情况,切换后秒表是否有效?

我不仅使用 Stopwatch 进行性能测量,而且还使用 Thread.Sleep 模拟计时器功能(以防止调用重叠)

4

2 回答 2

5

如果函数本身不是多线程的(例如,它不会产生其他线程/进程并等待它们完成),那么唯一的问题就是您的机器。

如果您的机器忙于做其他事情,它可能会使您的测试无效(例如,在进行 CPU 密集型测试时编码 H.264 视频)。同样,如果您使用所有物理内存来测试受内存限制的东西,那么它可能会使您的结果无效。

因此,一般原则是在进行此类测试时,机器应处于最小至正常负载下。除此之外没有多处理问题。是的,程序可以在运行时交换内核,但这样做的开销要么是你测量时间的一小部分,要么是测量时间太小,以至于系统时间测量的粒度是一个问题。

于 2009-07-19T08:48:44.173 回答
2

我认为您是在询问 Stopwatch 的低级实现以及在执行过程中切换处理器是否会使行为无效。该实现在内部确实使用了 QueryPerformanceCounter(请参阅 MS BCL 参考源;我至少在 .NET 4.0 中确认了它。)

此 API的MS 文档指出:

在多处理器计算机上,调用哪个处理器并不重要。但是,由于基本输入/输出系统 (BIOS) 或硬件抽象层 (HAL) 中的错误,您可能会在不同的处理器上获得不同的结果。

所以,你是对的;原则上,这无关紧要,但该评论表明已经观察到实现与预期接口不符的实例。如果您想保证测量的正确性,您可以使用线程亲和性,如您所述。也就是说,我猜观察到的任何错误都非常小,因为差异很大将是一个非常严重的 BIOS 或 HAL 错误。

于 2011-11-21T21:26:00.247 回答