我使用gettimeofday()
来计时一个简单的矩阵乘法示例,但我得到的结果接近两倍太长最初。在RHEL6服务器机器上,我得到的"糟糕"计时结果长达1秒(在本例中约65次单独计时)。我们所有的其他机器都是RHEL5工作站盒子,这段代码在它们上工作得更好;我最初只得到几个"坏"结果(前20毫秒)。
从这个网站上的帖子,我认为这可能与操作系统进程调度程序有关。如果取消下面第一个"for"语句的注释(从而通过重复初始化矩阵a、b和c来插入一个初始的忙循环),那么在RHEL5工作站和RHEL6服务器下,我将得到零"坏"结果。或者,如果我取消注释sleep语句,我会得到RHEL5和RHEL5的所有"坏"计时结果;RHEL6 .
由于某种原因,我的进程开始时只有大约一半的CPU访问权限,然后只要进程保持忙碌,它就可以"完全"访问CPU。如果它"休眠",然后恢复计时,它暂时也只能获得对CPU的全部访问权限的一半。
机器上没有其他事情发生(X未运行)。我曾尝试使用"chrt"来控制进程的优先级,但这并没有改变什么。我已经证实,在GCC 4.4.6和ICC 12.1.0中都会发生这种情况。我也试过"nice"。
代码如下:
#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 %fmsn",
m++, millisec, cum_ms );
// sleep( 2 );
}
printf( "a[%d][%d]=%fn", 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
无论优化级别(- 0、- 01、-O2等)如何,我都会遇到这个问题。
有谁知道在RHEL6服务器下是如何调度的吗?它和RHEL5工作站有很大的不同吗?我认为我看到的差异更多的是一个盒子是RHEL的服务器版,另一个是工作站版的功能(而不是版本5与6之间的差异)。是否有一些简单的方法来减少RHEL6服务器下的这种影响,使其更像RHEL5工作站盒子?
任何想法?谢谢。
不要使用gettimeofday(2)
进行性能测量。它太慢了,根本不适合这项工作。
用clock_gettime(2)
代替。它允许您从许多系统定义的计时器中进行选择。CLOCK_REALTIME是最简单的选择,但是如果有CLOCK_PROCESS_CPUTIME_ID可能更好。
处理器是否进入低功耗状态?像powertop这样的东西可以告诉你。(在Frequency stats选项卡中)