寻找一种精确的方法来微基准编写用C ++编写并在Linux / OSX上运行的代码路径

时间:2010-11-10 02:34:30

标签: c++ linux performance benchmarking

我正在寻找一些非常基本的小代码路径微基准测试,例如我用C ++编写的紧密循环。我在Linux和OSX上运行,并使用GCC。亚毫秒准确度有哪些设施?我想一个简单的测试运行代码路径很多次(数千万?)将给我足够的一致性,以获得良好的阅读。如果有人知道更好的方法,请随时提出建议。

4 个答案:

答案 0 :(得分:6)

您可以在x86 / x86_64上使用"rdtsc"处理器指令。对于多核系统,检查CPUID中的“constant_tsc”功能(linux中的/ proc / cpuinfo) - 这意味着所有内核都使用相同的滴答计数器,即使动态频率更改和休眠也是如此。

如果您的处理器不支持constant_tsc,请确保将程序绑定到核心(Linux中的taskset实用程序)。

在无序CPU上使用rdtsc时(除了Intel Atom之外,可能还有其他一些低端产品),请在之前添加“排序”指令,例如: “cpuid” - 它会暂时禁用指令重新排序。

此外,MacOsX还有“Shark”,它可以测量代码中的一些硬件事件。

RDTSC和无序CPU。有关优化的第2版Fog手册第18节中的更多信息:Optimizing subroutines in assembly language: An optimization guide for x86 platforms(包含所有五本手册的主要网站为http://www.agner.org/optimize/

http://www.scribd.com/doc/1548519/optimizing-assembly

  

在所有无序执行的处理器上,您必须插入XOR EAX,EAX / CPUID   每次读取计数器之前和之后,以防止它并行执行   还有别的。 CPUID是一个序列化指令,这意味着它刷新了   管道并等待所有待处理的操作完成后再继续。这非常有用   用于测试目的。

答案 1 :(得分:0)

这是我过去使用过的:

inline double gettime ()
{
    timeval tv;
    gettimeofday (&tv, NULL);
    return double (tv.tv_sec) + 0.000001 * tv.tv_usec;
}

然后:

double startTime = gettime();
// your code here
double runTime = gettime() - startTime;

这将引用微秒。

答案 2 :(得分:0)

Cachegrind / kCachegrind适用于非常细粒度的分析。我不相信它们可用于OS X,但是你在Linux上获得的结果应具有代表性。

答案 3 :(得分:0)

Microbenchmark应该在循环中运行相同的代码,最好是经过大量的迭代。 我使用以下内容并将其与时间(1)实用程序一起运行;

观察到以下警告

  • 如果测试没有产生打印出的计算,那么代码会通过优化消除 - gcc使用-O3就可以了。

  • test()和lookup()的测试函数必须在与迭代循环不同的源文件中实现;如果它们在同一个文件中并且查找函数返回常量值,那么代码优化就不会调用它,而不是一次,它只会将返回值乘以迭代次数!

file main.c

#include <stdio.h>

#define RUN_COUNT 10000000

void init();
int  lookup();


main()
{
  int sum = 0;
  int i;

  init();


  for(i = 0; i < RUN_COUNT; i++ ) {
    sum  += lookup();
  }

  printf("%d", sum );
}