2010-05-12 6 views
0

편집 :이 긴 게시물을 모두 작성한 후에 문제가 발견되었습니다. 누군가가 나에게 잘못한 것에 대해 좋은 대답을 줄 수 있다면 실행 시간을 초 단위로 어떻게 얻을 수 있습니까 (소수점 이하 5 자리 수를 사용). 허용 된 것으로 표시 할 것입니다. 힌트 : clock_getttime() 맨 페이지를 해석하는 방법에 문제가있었습니다.코드 블록의 실행 시간을 N 배로 측정하는 데 문제가 있음

안녕,

의 나는 내가의 실행 시간을 측정 할 필요가 myOperation이라는 함수가 있다고 가정 해 봅시다. 그것을 측정하기 위해 clock_gettime()을 사용했기 때문에 here을 주석 중 하나에 포함 시켰습니다.

교사는 최종 보고서의 평균, 표준 편차 및 중간 값을 얻을 수 있도록 N 번 측정하도록 권장합니다. 그는 또한 하나 대신에 myOperationM 번을 실행하도록 권장합니다. myOperation이 매우 빠른 작업 인 경우, M 번 측정하면 "실시간"이라는 느낌을 갖습니다. 사용되는 클록이 이러한 연산을 측정하는 데 필요한 정밀도를 갖지 않을 수 있기 때문입니다. 그러므로, 실행 myOperation은 한 번만 실행하거나 M 번 실행하는 데 시간이 많이 걸립니다.

해당 문제를 처리하는 데 M 번 실행하고 있습니다. M가 증가하면 최종 평균값이 감소합니다. 나는 나에게 이해가 가지 않는다. 이렇게하면 평균적으로 A 지점에서 B 지점으로 이동하는 데 평균 3 ~ 5 초가 걸릴 수 있습니다. 그런 다음 A에서 B로 이동하여 A로 5 회 돌아갑니다 (A에서 B까지 B로 동일하게 10 번합니다. ~로) 당신은 그것을 측정합니다. 당신이 10으로 나눌 때보 다 평균은 3에서 5 초인 A 지점에서 B 지점으로 이동하는 평균과 같습니다.

이것은 내 코드에서 수행해야하지만 작동하지 않습니다. 내가 A에서 B로 돌아가는 횟수를 계속 늘리면 평균이 낮아지고 낮을수록 나에게 의미가 없습니다. 위의 diffTimeClock 기능이 blog post에서입니다 :

#include <stdio.h> 
#include <time.h> 

#define MEASUREMENTS 1 
#define OPERATIONS 1 

typedef struct timespec TimeClock; 

TimeClock diffTimeClock(TimeClock start, TimeClock end) { 
    TimeClock aux; 

    if((end.tv_nsec - start.tv_nsec) < 0) { 
     aux.tv_sec = end.tv_sec - start.tv_sec - 1; 
     aux.tv_nsec = 1E9 + end.tv_nsec - start.tv_nsec; 
    } else { 
     aux.tv_sec = end.tv_sec - start.tv_sec; 
     aux.tv_nsec = end.tv_nsec - start.tv_nsec; 
    } 

    return aux; 
} 

int main(void) { 
    TimeClock sTime, eTime, dTime; 
    int i, j; 

    for(i = 0; i < MEASUREMENTS; i++) { 
     printf(" » MEASURE %02d\n", i+1); 

     clock_gettime(CLOCK_REALTIME, &sTime); 

     for(j = 0; j < OPERATIONS; j++) { 
      myOperation(); 
     } 

     clock_gettime(CLOCK_REALTIME, &eTime); 

     dTime = diffTimeClock(sTime, eTime); 

     printf(" - NSEC (TOTAL): %ld\n", dTime.tv_nsec); 
     printf(" - NSEC (OP): %ld\n\n", dTime.tv_nsec/OPERATIONS); 
    } 

    return 0; 
} 

주 :

충분한 이론은, 여기 내 코드입니다. 코드의 긴 블록을 게시해야하므로 내 실제 기능을 게시하는 데 아무런 의미가 없으므로 실제 작업을 myOperation()으로 바꿨습니다. 원하는 경우 코드를 컴파일하고자하는 내용으로 쉽게 코드 할 수 있습니다. 당신이 볼 수 있듯이

, OPERATIONS = 1 결과는 다음과 같습니다

» MEASURE 01 
    - NSEC (TOTAL): 27456580 
    - NSEC (OP): 27456580 

OPERATIONS = 100에 대한 결과는 다음과 같습니다

» MEASURE 01 
    - NSEC (TOTAL): 218929736 
    - NSEC (OP): 2189297 

OPERATIONS = 1000에 대한 결과는 다음과 같습니다 OPERATIONS = 10000를 들어

» MEASURE 01 
    - NSEC (TOTAL): 862834890 
    - NSEC (OP): 862834 

결과는 다음과 같습니다 :

» MEASURE 01 
    - NSEC (TOTAL): 574133641 
    - NSEC (OP): 57413 

지금, 나는 실제로 수학과는 거리가 멀지 만, 이것은 나에게 전혀 의미가 없습니다.나는 이미이 문제에 관해 나와 함께이 프로젝트에있는 친구와 이야기를 나누었고 그 차이점을 이해할 수도 없다. 내가 왜 OPERATIONS을 증가시킬 때 값이 점점 더 낮아지고 낮아지고 있는지 이해할 수 없습니다. 작업 자체는 몇 번이나 실행하더라도 동일한 시간 (평균적으로 똑같은 시간이 아님)을 가져야합니다.

당신은 실제로 작동 자체, 데이터가 읽혀지고 일부 데이터는 이미 캐시와 bla bla에있을 수 있지만, 나는 그것이 문제라고 생각하지 않는다고 말할 수 있습니다. 필자의 경우 myOperation은 CSV 파일에서 5000 줄의 텍스트를 읽고 값을 ;으로 분리하여 데이터 구조에 삽입합니다. 각 반복마다 데이터 구조를 파괴하고 다시 초기화합니다.

생각해 보니 clock_gettime()으로 시간을 측정하는 데 문제가 있다고 생각합니다. 아마도 제대로 사용하지 않을 수도 있습니다. 마지막 예제를 보자. 여기서는 OPERATIONS = 10000이다. 총 소요 시간은 574133641ns 였는데 대략 0.5 초가 될 것입니다. 그건 불가능 해요, 기다리는 화면을 보지 못하고 뭔가 먹으러 갔을 때 몇 분이 걸렸습니다.

+0

두 이벤트 사이의 벽시계 시간을 측정했기 때문에 'CLOCK_REALTIME'대신 'CLOCK_MONOTONIC'을 사용해야합니다. 시스템 시간이 변경되면 후자가 점프 할 수 있으며 전자는 영향을받지 않습니다. – caf

+0

예, 실제로 시스템을 수동으로 변경하지 않고 시스템 시간이 변경되는 이유는 무엇입니까? –

+0

'ntpd '와 같은 시스템 데몬이 그것을 변경했기 때문에? (또는 공유 시스템의 시스템 관리자입니까?) – caf

답변

1
당신은 단지 double로, 초 차이의 수를 반환하기 위해 diffTimeClock() 기능을 변경해야

하십시오 double

double diffTimeClock(TimeClock start, TimeClock end) { 
    double diff; 

    diff = (end.tv_nsec - start.tv_nsec)/1E9; 
    diff += (end.tv_sec - start.tv_sec); 

    return diff; 
} 

메인 루틴 변화 dTime에, 그리고 printfs가 맞게 :

printf(" - SEC (TOTAL): %f\n", dTime); 
printf(" - SEC (OP): %f\n\n", dTime/OPERATIONS); 
0

일반적으로이 함수는 time() 함수를 사용합니다. 그것은 벽시계 시간을 보여 주지만, 그것은 결국 내가 궁금해하는 것입니다.

성능 테스트에서 하나의 문제는 운영 체제가 파일 시스템 관련 작업을 캐시 할 수 있다는 것입니다. 따라서 두 번째 (이상) 실행은 첫 번째 실행보다 훨씬 빠릅니다. 일반적으로 작업을 테스트하고 결과를 평균하여 변경 한 결과에 대한 좋은 느낌을 얻으십시오. 노이즈를 필터링하는 데 도움이되는 많은 변수가 있습니다.

1

TimeClock 유형에는 초와 나노초 두 개의 필드가있는 것처럼 보입니다. nanosec 필드를 작업 수로 나누는 것은 의미가 없습니다. 총 시간을 나누어야합니다.

1

당신은 gettimeofday이있는 POSIX 시스템()를 사용하는 경우 당신이 마이크로 현재 시간을 얻기 위해이 같은 것을 사용할 수 있습니다 기능 :

long long timeInMicroseconds(void) { 
    struct timeval tv; 

    gettimeofday(&tv,NULL); 
    return (((long long)tv.tv_sec)*1000000)+tv.tv_usec; 
} 

이 매우 편리 이유 위해서이다 당신의 기능은 바로이 작업을 수행해야했다 얼마나 많은 계산 :

long long start = timeInMicroseconds(); 
... do your task N times ... 
printf("Total microseconds: %lld", timeInMicroseconds()-start); 

그래서 당신은 두 개의 정수, 초 하나와 마이크로 하나 처리 할 필요가 없습니다. 시간을 더하거나 빼면 확실한 방법으로 작동합니다.

+0

당신이 깨달은 지 모르겠지만, 당신이 말했던 것처럼, "두 개의 정수를 다룰 필요가 없을 것"이라고 말했을뿐입니다. 'return ((long long) tv.tv_sec) * 1000000) + tv.tv_usec;'를 보라. 내 원래의 문제를 해결하기 위해 비슷한 일을했고 마이크로 대신 나노 정밀도를 사용했습니다. –

+0

예, 한 시간을 다른 시간으로 빼야 할 때 명시 적으로 두 개의 정수를 처리하지 말아야합니다. 그렇지 않으면 나노초의 오버플로를 확인하기가 더 어려워집니다. 그런 다음 1 초를 빼고 원래 결과에 1000000 나노초를 더합니다). 대신에 당신이 한 것처럼, 마이크로 초 단위로 시간을 생성하는 함수에서만 두 정수를 다룰 것입니다. 나머지 모든 코드는 사소한 단일 번호 만 사용합니다. – antirez

+0

이미'diffTimeClock()'에서 이미 그렇게하고 있습니다. 그래서 나는 당신의 게시물을 정말로 이해하지 못합니다 ... –

관련 문제