2011-12-30 4 views
3

간단한 행렬 곱하기 예제를 사용하기 위해 gettimeofday()을 사용하고 있는데, 처음에는 두 배 가까이에 결과가 나타납니다. RHEL6 서버 시스템에서, "나쁜"타이밍 결과가 최대 1 초 동안 발생합니다 (이 예에서는 ~ 65 개별 타이밍). 우리의 다른 모든 머신은 RHEL5 워크 스테이션 박스이며이 코드는 보다 우수합니다. 나는 초기에 단지 2 개의 "나쁜"결과만을 얻는다 (처음 20 밀리 초 동안).gettimeofday를 사용한 초기 타이밍 결과가 느림 - RHEL6 서버에서 악화됨

이 사이트의 게시물을 보면 아마도 OS 프로세스 스케줄러와 관련이 있다고 생각합니다. 아래의 첫 번째 "for"구문의 주석을 제거하면 (즉, 행렬 a, b 및 c를 반복적으로 초기화하여 초기 사용 중 루프를 삽입 함) RHEL5 Workstation 및 RHEL6 Server 모두에서 "불량"결과가 0이됩니다. 또는 sleep 문을 주석 처리하지 않으면 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]); 
} 

여기가 그 결과 다음과 같습니다 :

여기 코드의 I에 관계없이 최적화 레벨 (-O0, -O1, -O2, 등)의 문제가 발생

% 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 

.

누군가 RHEL6 서버에서 스케줄링이 수행되는 방법에 대해 알고 있습니까? RHEL5 워크 스테이션과 매우 다른가요? 나는 하나의 박스가 RHEL의 서버 에디션이고 다른 하나는 워크 스테이션 에디션 (릴리스 5와 6의 차이보다는)이라는 사실에 더 많은 차이가 있다고 생각한다. RHEL6 서버에서이 효과를 줄이고 RHEL5 워크 스테이션 상자처럼 작동시키는 간단한 방법이 있습니까?

아이디어가 있으십니까? 감사.

+0

은 서버가 과도하게 컨텍스트를 전환해야하기 때문일 수 있습니다. 계산이 끝났지 만'gettimeofday()'는 이후에 호출되는 상황을 초래합니다. 그냥 내 $ 0.02 –

+0

당신은 전용 서버를 사용하고 있습니다. –

+0

두 서버에서 동일한 JVM입니까? – fge

답변

2

프로세서가 저전력 상태가 될 수 있습니까? 파워 탑 같은 것이 당신에게 말할 수 있습니다. (빈도 통계 탭에서)

+0

매우 흥미로운 제안. 나는 파워 톱에 대해 듣지 못했다. 맨 위에는 "P-States (주파수)"아래에 아무것도 없습니다. 내가보고있는 것을 이해하기 위해서는 좀 더 살펴야합니다. 제안 해 주셔서 감사합니다. 이 점에서 RHEL5 워크 스테이션 상자를 RHEL5 워크 스테이션 상자처럼 실행할 수있는 방법을 알고 싶습니다.감사. – chrisG

+0

이것이 지금까지 최고의 리드라고 생각합니다. Powertop 2.0 [link] (http://www.h-online.com/open/features/Powertop-2-0-saving-power-under-Linux-1257057.html)은 매우 인상적입니다. 불행히도 상대적으로 최근의 커널 (> 2.6.36)이 필요하기 때문에 RHEL5 또는 RHEL6에서 현재 나를위한 옵션이 아닙니다. 나는 내 노트북 ​​(Ubuntu 11.10)에서 내가 무엇을 찾을 수 있는지 알아보기 위해 노력할 것이다. – chrisG

+0

이 현상이 일어나고있는 것 같습니다. Powertop 1.97을 설치할 수있었습니다. 불행히도, "튜너 블"탭에서 오해의 소지가있는 정보를 얻었습니다. 그것은 "온 디맨드"cpufreq 주지사가 운영되고 있다고 말했습니다. 사실, cpufreq는 전혀 실행되지 않습니다. *하지만 * cpuidle 실제로 활성화되어 있습니다 (특히 intel_idle acpi_idle 대신 실행되고 있지만 두 사이를 전환했습니다). 위대한 정보 cpuidle 여기에 : [링크] (http://lwn.net/Articles/384146/). 결론 : 모든 12 개의 코어가 타이밍 호출을 중단 할 때 최저 전력 상태 (높은 대기 시간)에서 모든 시간을 소비합니다. – chrisG

4

성능 측정에 gettimeofday(2)을 사용하지 마십시오. 그것은 너무 느리고 단순히 직업을 위해 설계되지 않았습니다.

대신 clock_gettime(2)을 사용하십시오. 시스템 정의 타이머 중 하나에서 선택할 수 있습니다. CLOCK_REALTIME은 가장 쉬운 선택이지만 CLOCK_PROCESS_CPUTIME_ID가 있으면 더 좋을 수 있습니다.

관련 문제