我正在尝试做一些性能测试。我发现与Visual C ++(2010)调试运行时链接的代码似乎比与发布运行时链接的运行速度更快。
我可以使用非常简单的代码片段和构建命令行重现问题:
#include <sys/timeb.h>
#include <time.h>
#include <stdio.h>
int main() {
unsigned int *a= new unsigned int[100000000];
unsigned int v = 0xaabbccdd;
timeb start, end;
ftime(&start);
clock_t start_cycle = clock();
for (register int i=0; i<100000000; i++) {
a[i] += v;
}
clock_t end_cycle = clock();
ftime(&end);
printf ("elapsed time: %d ms\n", ((end.time - start.time)*1000 +
end.millitm - start.millitm));
printf ("cycles: %d\n", end_cycle - start_cycle);
delete a;
return end_cycle - start_cycle;
}
$ cl / O2 / MT test.cc
已用时间:176毫秒
$ cl / O2 / MTd test.cc
已用时间:88毫秒
$ cl / MT test.cc
已用时间:523 ms
$ cl / MTd test.cc
已用时间:480毫秒
当我添加/ Fa选项时,两者都生成相同的汇编代码。
使用MingW32 g ++ -O3构建它给出了类似的发布版本结果:
$ g ++ -O3 test.cc
已用时间:172毫秒
我想知道VC调试运行时如何如此之快。它是否优化/省略了我不知道的东西?
答案 0 :(得分:3)
unsigned int *a= new unsigned int[100000000];
你正在犯一个传统的基准错误,你启动计时器太晚了。在需求分页的虚拟内存操作系统(如Windows)上,该语句仅分配地址空间。只是处理器的数字,分配中每个4096字节一个。它不分配物理内存,只是虚拟内存。
直到稍后,实际开始访问数组元素时才会发生这种情况。这会生成页面错误,即需求分页功能,强制操作系统将地址空间映射到RAM。您的程序将生成97657页错误(100000000 * 4/4096)。
当发生这些页面错误时,调试版本和发布版本之间的区别恰好是。在发布版本中,它们出现在for()循环中,其成本包含在测量中。应该如此。
但是当使用/ MTd或/ MDd构建时,您将使用调试分配器。当您调用未定义的行为并使用未初始化的内存时,哪个initializes allocated heap blocks具有可能使程序崩溃的位模式。初始化会导致相同的页面错误。但是在启动计时器之前发生。所以你的测量是关闭的,它不包括内存映射成本。
您需要在分配之前启动计时器以比较苹果和橙子。