2010-06-12 59 views
3

我学习使用gprof的,然后我得到这个代码怪异的结果:奇怪探查行为:相同的功能,不同的表演

int one(int a, int b) 
{ 
    int i, r = 0; 
    for (i = 0; i < 1000; i++) 
    { 
     r += b/(a + 1); 
    } 
    return r; 
} 

int two(int a, int b) 
{ 
    int i, r = 0; 
    for (i = 0; i < 1000; i++) 
    { 
     r += b/(a + 1); 
    } 
    return r; 
} 

int main() 
{ 
    for (int i = 1; i < 50000; i++) 
    { 
     one(i, i * 2); 
     two(i, i * 2); 
    } 
    return 0; 
} 

,这是探查输出

% cumulative self    self  total   
time seconds seconds calls us/call us/call name  
50.67  1.14  1.14 49999 22.80 22.80 two(int, int) 
49.33  2.25  1.11 49999 22.20 22.20 one(int, int) 

如果我呼叫一个然后两个结果是相反的,两个需要更多的时间比一个
都是相同的功能,但第一个电话总是花费较少的时间,然后第二个

这是为什么?

注:汇编代码是完全一样的和代码正在与没有优化编译

+1

这些是非常小的差异,可能是由于任何数量的事情。如果你正在学习使用gprof,你应该知道它的缺点:http://stackoverflow.com/questions/1777556/alternatives-to-gprof/1779343#1779343 – 2010-06-13 13:17:20

+0

好文本。非常感谢:D – arthurprs 2010-06-13 14:57:53

回答

1

我猜它是在运行时优化一些侥幸 - 一个使用寄存器和其他没有或像这样的小事。

系统时钟可能运行到100nsec的精度。平均通话时间30nsec或25nsec小于一个时钟周期。时钟周期的5%舍入误差相当小。两次都接近零。

+0

汇编代码是完全一样的,这是我第一次认为我咀嚼。我修改了代码以在函数上花费更多时间,差异真的下降了,但仍然存在。我认为这是由一些CPU行为造成的:分支预测,缓存未命中等。 – arthurprs 2010-06-12 16:19:09

0

它总是第一个被称为稍慢的?如果是这样的话,我会猜测这是一个CPU缓存做它的事情。或者它可能是操作系统的懒惰分页。

顺便说一句:哪些优化标志正在编译?

+0

是的,我想它是缓存或类似的东西。没有优化。 – arthurprs 2010-06-12 16:31:35

1

我的猜测:这是mcount数据被解释的方式的人为因素。 mcount(monitor.h)的粒度大小为32位长字 - 我的系统上有4个字节。所以你不会期待这个:在EXACT同一个mon.out文件中,我从prof vs gprof得到了不同的报告。 solaris 9 -

prof 
%Time Seconds Cumsecs #Calls msec/call Name 
    46.4 2.35 2.3559999998  0.0000 .div 
    34.8 1.76 4.11120000025  0.0000 _mcount 
    10.1 0.51 4.62  1 510.  main 
    5.3 0.27 4.8929999999  0.0000 one 
    3.4 0.17 5.0629999999  0.0000 two 
    0.0 0.00 5.06  1  0.  _fpsetsticky 
    0.0 0.00 5.06  1  0.  _exithandle 
    0.0 0.00 5.06  1  0.  _profil 
    0.0 0.00 5.06  20  0.0  _private_exit, _exit 
    0.0 0.00 5.06  1  0.  exit 
    0.0 0.00 5.06  4  0.  atexit 


gprof 
    % cumulative self    self total 
time seconds seconds calls ms/call ms/call name 
71.4  0.90  0.90  1 900.00 900.00 key_2_text  <cycle 3> [2] 
    5.6  0.97  0.07 106889  0.00  0.00 _findbuf [9] 
    4.8  1.03  0.06 209587  0.00  0.00 _findiop [11] 
    4.0  1.08  0.05       __do_global_dtors_aux [12] 
    2.4  1.11  0.03       mem_init [13] 
    1.6  1.13  0.02 102678  0.00  0.00 _doprnt [3] 
    1.6  1.15  0.02       one [14] 
    1.6  1.17  0.02       two [15] 
    0.8  1.18  0.01 414943  0.00  0.00 realloc <cycle 3> [16] 
    0.8  1.19  0.01 102680  0.00  0.00 _textdomain_u  <cycle 3> [21] 
    0.8  1.20  0.01 102677  0.00  0.00 get_mem [17] 
    0.8  1.21  0.01       $1 [18] 
    0.8  1.22  0.01       $2 [19] 
    0.8  1.23  0.01       _alloc_profil_buf [22] 
    0.8  1.24  0.01       _mcount (675) 
+0

我没有提及的一点是:在两个()和一个()中花费的时间在上述两个报告中有所不同。在一个时代是平等的,另一个则不是。 – 2010-06-12 19:19:02