如何测量x86下纳秒以下的时间?

我搜索并使用了许多方法来测量经过的时间。 为此目的有很多问题。 例如, 这个问题非常好,但是当你需要一个准确的时间记录器时,我找不到一个好的方法。 为此,我想在这里分享我的方法以便在出现问题时予以纠正。

更新和注意:这个问题是基准测试,不到一纳秒。 它与使用clock_gettime(CLOCK_MONOTONIC,&start);完全不同clock_gettime(CLOCK_MONOTONIC,&start); 它记录的时间超过一纳秒。

更新:测量加速的常用方法是重复应该进行基准测试的程序部分。 但是,正如评论中所提到的,当研究人员依赖自动向量化时,它可能会显示出不同的优化。

注意一次重复测量经过的时间是不够准确的。 在某些情况下,我的结果显示该部分必须重复超过1K或1M才能获得最短的时间。

建议:我不熟悉shell编程(只知道一些基本命令……)但是,有可能测量最小的时间而不重复程序内部。

我的当前解决方案为了防止分支,我使用宏#define REP_CODE(X) XX X... XX重复ode部分,其中X是我想要基准的代码部分,如下所示:

 //numbers #define FMAX1 MAX1*MAX1 #define COEFF 8 int __attribute__(( aligned(32))) input[FMAX1+COEFF]; //= {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17}; int __attribute__(( aligned(32))) output[FMAX1]; int __attribute__(( aligned(32))) coeff[COEFF] = {1,2,3,4,5,6,7,8};//= {1,1,1,1,1,1,1,1};//; //= {1,2,1,2,1,2,1,2,2,1}; int main() { REP_CODE( t1_rdtsc=_rdtsc(); //Code for(i = 0; i < FMAX1; i++){ for(j = 0; j < COEFF; j++){//IACA_START output[i] += coeff[j] * input[i+j]; }//IACA_END } t2_rdtsc=_rdtsc(); ttotal_rdtsc[ii++]=t2_rdtsc-t1_rdtsc; ) // The smallest element in `ttotal_rdtsc` is the answer } 

这不会影响优化,但也会受到代码大小的限制,并且在某些情况下编译时间过长。

有任何建议和更正吗?

提前致谢。

如果您对autovectorizer有疑问并希望限制它,只需添加一个asm("#somthing"); 在您的begin_rdtsc ,它将分离do-while循环。 我刚刚检查过,它将你发布的代码矢量化,自动矢量化器无法对其进行矢量化。 我改变你的宏,你可以使用它….

 long long t1_rdtsc, t2_rdtsc, ttotal_rdtsc[do_while], ttbest_rdtsc = 99999999999999999, elapsed, elapsed_rdtsc=do_while, overal_time = OVERAL_TIME, ttime=0; int ii=0; #define begin_rdtsc\ do{\ asm("#mmmmmmmmmmm");\ t1_rdtsc=_rdtsc(); #define end_rdtsc\ t2_rdtsc=_rdtsc();\ asm("#mmmmmmmmmmm");\ ttotal_rdtsc[ii]=t2_rdtsc-t1_rdtsc;\ }while (ii++ 

我已经开发出了我的第一个答案,并得到了这个解 但是,我仍然想要一个解决方案。 因为准确测量时间和影响最小非常重要。 我将此部分放在头文件中并将其包含在主程序文件中。

 //Header file header.h #define count 1000 // number of repetition long long t1_rdtsc, t2_rdtsc, ttotal_rdtsc[count], ttbest_rdtsc = 99999999999999999, elapsed, elapsed_rdtsc=count, overal_time = OVERAL_TIME, ttime=0; int ii=0; #define begin_rdtsc\ do{\ t1_rdtsc=_rdtsc(); #define end_rdtsc\ t2_rdtsc=_rdtsc();\ ttotal_rdtsc[ii]=t2_rdtsc-t1_rdtsc;\ }while (ii++ 

我建议将此方法用于x86微架构。

注意:

  1. NUM_LOOP应该是一个数字,有助于提高重复代码记录最佳时间的准确性
  2. ttbest_rdtsc必须大于我建议最大化它的最差时间。

  3. 我使用(你可能不想要它) OVERAL_TIME作为另一个检查规则,因为我在许多内核中使用它,在某些情况下NUM_LOOP非常大,我不想改变它。 我计划OVERAL_TIME限制迭代并在特定时间后停止。

更新:整个程序是这样的:

 #include  #include  #define NUM_LOOP 100 //executes your code NUM_LOOP times to get the smalest time to avoid overheads such as cache misses, etc. int main() { long long t1_rdtsc, t2_rdtsc, ttotal_rdtsc, ttbest_rdtsc = 99999999999999999; int do_while = 0; do{ t1_rdtsc = _rdtsc(); //put your code here t2_rdtsc = _rdtsc(); ttotal_rdtsc = t2_rdtsc - t1_rdtsc; //store the smalest time: if (ttotal_rdtsc 

我已经改为这个并添加到我自己的标题中然后我可以在我的程序中使用它。

 #include  #define do_while NUM_LOOP #define OVERAL_TIME 999999999 long long t1_rdtsc, t2_rdtsc, ttotal_rdtsc, ttbest_rdtsc = 99999999999999999, elapsed, elapsed_rdtsc=do_while, overal_time = OVERAL_TIME, ttime=0; #define begin_rdtsc\ do{\ t1_rdtsc=_rdtsc(); #define end_rdtsc\ t2_rdtsc=_rdtsc();\ ttotal_rdtsc=t2_rdtsc-t1_rdtsc;\ if (ttotal_rdtsc 

如何使用这种方法? 嗯,这很简单!

 int main() { //before the section begin_rdtsc //put your code here to measure the clocks. end_rdtsc return 0 } 

要有创意,你可以改变它来衡量你的程序的加速等。输出的一个例子是:

 the best is 9600 in 384751th iteration and 569179 repetitions 

我测试的代码得到了9600时钟,最佳记录在384751end迭代中,我的代码测试了569179

我在GCC和Clang上测试了它们。