使用gettimeofday缓慢的初始计时结果 - 在RHEL6 Server下更糟糕

时间:2011-12-30 20:26:08

标签: c linux scheduler rhel gettimeofday

我正在使用gettimeofday()来计算一个简单的矩阵乘法示例,但我得到的结果最近接近两倍。在RHEL6服务器计算机上,我得到的“坏”计时结果长达近1秒(在此示例中约为65个单独计时)。我们所有的其他机器都是RHEL5工作站盒子,这些代码可以更好地工作很多;我最初只得到几个“坏”结果(第一个~20毫秒)。

从本网站的帖子来看,我认为这可能与操作系统进程调度程序有关。如果我取消注释下面的第一个“for”语句(从而通过重复初始化矩阵a,b和c插入一个初始忙循环),我在RHEL5 Workstation和RHEL6 Server下得到零“坏”结果。或者,如果我取消注释睡眠声明,我会得到RHEL5&的所有“坏”时序结果。 RHEL6。

出于某种原因,我的进程最初启动时只有大约一半的CPU访问权限,只要进程保持繁忙,它就会“完全”访问CPU。如果它“休眠”然后恢复计时,它再次暂时只能获得大约一半的CPU访问权。

机器上没有其他任何事情发生(X未运行)。我试过“chrt”来控制进程的优先级,但是没有改变。我已经用GCC 4.4.6和ICC 12.1.0验证了这种情况。我也试过“很好”。

以下是代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#define N 225
#define DELAY_LOOPS 8000
main() {
  struct timeval _t0, _t1, _t2;
  double a[N][N], b[N][N], c[N][N];
  double millisec, cum_ms;
  int i, j, k, l, m=0;
  gettimeofday( &_t0, NULL );
  // for( l=0; l<DELAY_LOOPS; l++ )
    for( i=0; i<N; i++ )
      for( j=0; j<N; j++ ) {
        a[i][j]=0;
        b[i][j]=i;
        c[i][j]=j;
      }
  for( l=0; l<75; l++ ) {
    gettimeofday( &_t1, NULL );
    for( i=0; i<N; i++ )
      for( j=0; j<N; j++ )
        for( k=0; k<N; k++ )
          a[i][j]+=b[i][k]*c[k][j];
    gettimeofday( &_t2, NULL );
    millisec  = 1000*(_t2.tv_sec-_t1.tv_sec);
    millisec += 1e-3*(_t2.tv_usec-_t1.tv_usec);
    cum_ms  = 1000*(_t2.tv_sec-_t0.tv_sec);
    cum_ms += 1e-3*(_t2.tv_usec-_t0.tv_usec);
    printf( "%d: duration %fms, cumulative %fms\n",
            m++, millisec, cum_ms );
    // sleep( 2 );
  }
  printf( "a[%d][%d]=%f\n", N/2, N/2, a[N/2][N/2] );
}

以下是结果:

% icc -O2 -o test main.c; ./test
0: duration 13.049000ms, cumulative 13.677000ms
1: duration 13.026000ms, cumulative 26.753000ms
2: duration 12.911000ms, cumulative 39.668000ms
3: duration 12.913000ms, cumulative 52.584000ms
4: duration 12.914000ms, cumulative 65.501000ms
5: duration 12.911000ms, cumulative 78.415000ms
6: duration 12.912000ms, cumulative 91.331000ms
/* snip */
64: duration 12.912000ms, cumulative 840.633000ms
65: duration 10.455000ms, cumulative 851.092000ms
66: duration 5.910000ms, cumulative 857.004000ms
67: duration 5.908000ms, cumulative 862.914000ms
68: duration 5.907000ms, cumulative 868.823000ms
69: duration 5.908000ms, cumulative 874.732000ms
70: duration 5.912000ms, cumulative 880.646000ms
71: duration 5.907000ms, cumulative 886.554000ms
72: duration 5.907000ms, cumulative 892.462000ms
73: duration 5.908000ms, cumulative 898.372000ms
74: duration 5.908000ms, cumulative 904.281000ms
a[112][112]=211680000.000000

无论优化级别如何(-O0,-O1,-O2等),我都会遇到问题。

有没有人知道如何在RHEL6服务器下完成调度?它与RHEL5工作站有很大不同吗?我认为我看到的差异更多的是这样一个事实,即一个盒子是RHEL的服务器版本,另一个是工作站版本(而不是版本5与6之间的差异)。是否有一些简单的方法可以减少RHEL6 Server下的这种影响并使其更像RHEL5 Workstation框?

有什么想法吗?感谢。

2 个答案:

答案 0 :(得分:4)

请勿使用gettimeofday(2)进行效果衡量。它太慢了,根本不适合这项工作。

请改用clock_gettime(2)。它允许您从众多系统定义的定时器中选择一个。 CLOCK_REALTIME是最简单的选择,但如果你有CLOCK_PROCESS_CPUTIME_ID可能会更好。

答案 1 :(得分:2)

处理器能否进入低功耗状态?像powertop这样的东西可以告诉你。 (在频率属性标签中)