경과 시간을 쉽게 측정


297

프로그램의 다양한 지점을 측정 하기 위해 time () 을 사용하려고합니다 .

내가 이해하지 못하는 것은 이전과 이후의 값이 같은 이유입니다. 나는 이것이 내 프로그램을 프로파일 링하는 가장 좋은 방법은 아니라는 것을 이해하고 있습니다.

printf("**MyProgram::before time= %ld\n", time(NULL));

doSomthing();
doSomthingLong();

printf("**MyProgram::after time= %ld\n", time(NULL));

나는 시도했다 :

struct timeval diff, startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

timersub(&endTV, &startTV, &diff);

printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec);

결과는 **time taken = 0 26339어떻게 읽 습니까? 26,339 나노초 = 26.3 밀리 초를 의미합니까?

무엇에 대해 **time taken = 4 45025, 그 평균 사초 25 밀리 초를합니까?


10
질문을 이해하지 못합니다. 물론 값이 다릅니다. 시간이지나면서 time()다른 값을 반환합니다.
토마스

1
"이전과 이후의 값이 다른 이유를 이해하지 못한다"는 것은 무엇을 의미합니까? time(NULL)...를 사용하여 현재 시간을 (1970 년 1 월 1 일 이후 초 단위로) 받고 있습니다. t 완료하는 데 1 초가 걸립니다.이 경우 첫 번째와 동일합니다).
Brian Roach

1
인쇄 내용과 스톱워치 또는 벽시계 (또는 달력)로 시간을 측정하는 데 얼마나 걸립니까?
매트 커티스

4
죄송합니다. 두 값이 모두 동일합니다. 질문을 잘못 입력했습니다.
hap497

2
이 스레드를 참조하십시오 : stackoverflow.com/questions/275004/…
기본값

답변:


336
//***C++11 Style:***
#include <chrono>

std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();

std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl;
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::nanoseconds> (end - begin).count() << "[ns]" << std::endl;

10
네, 이것이 정답입니다
Ferenc Dajka

23
당신은 추가해야이 프로그램을 실행하려면 #include <chrono>: 지시어를 내가 같이보고 시간을 변경할 것입니다 std::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl;: (그리고 C ++ 컴파일 11 플래그 잊지 마세요 -std=c++11)
안토

1
그런데 이것은 벽시계 시간이 아니라 CPU 시간을 측정합니다. 권리?
Nikos

4
@ RestlessC0bra cppreference의 문서에 따르면, "이 시계는 벽시계 시간과 관련이 없으며 (예 : 마지막 재부팅 이후의 시간 일 수 있음) 간격 측정에 가장 적합합니다."
cylus

1
std :: chrono :: duration_cast <std :: chrono :: microseconds> (end-begin) .count ()
sqp_125

272
#include <ctime>

void f() {
  using namespace std;
  clock_t begin = clock();

  code_to_time();

  clock_t end = clock();
  double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
}

time()기능은 1 초 이내에만 정확하지만 CLOCKS_PER_SEC1 초 내에 "시계"가 있습니다. 과도하게 단순화 되었더라도 쉽고 휴대용 측정입니다.


129
clock()실제 경과 시간이 아니라 CPU 시간 을 측정 한다는 점에 유의하십시오 (이보다 클 수 있음).
jlstrecker

12
클러스터의 병렬 코드를 프로그래밍 할 때이 방법은 실제 시간을 반영하지 않습니다.
Nicholas Hamilton

3
이것은 가장 쉬운 방법으로 보입니다. @jlstrecker 의견을 업데이트하거나 처리 하시겠습니까?
Lorah Attkins

5
위에 게시 된 솔루션은 여러 가지 이유로 좋은 솔루션이 아닙니다. 정답입니다.- stackoverflow.com
questions

1
나는이 솔루션을 시도했으며 의견에서 제안했듯이 내 타이머는 실제 시간보다 훨씬 빠르게 실행되었습니다.
RTbecard

267

타이머 구조를 통해 호출 함으로써 시간 측정 메커니즘을 추상화하고 최소한의 추가 코드로 각 호출 가능 런타임을 측정 할 수 있습니다 . 또한 컴파일 타임 에 타이밍 유형 (밀리 초, 나노초 등)을 매개 변수화 할 수 있습니다 .

Loki Astari 의 검토 와 다양한 템플릿 사용 제안에 감사합니다 . 이것은 왜 전달 함수 호출이다.

#include <iostream>
#include <chrono>

template<typename TimeT = std::chrono::milliseconds>
struct measure
{
    template<typename F, typename ...Args>
    static typename TimeT::rep execution(F&& func, Args&&... args)
    {
        auto start = std::chrono::steady_clock::now();
        std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
        auto duration = std::chrono::duration_cast< TimeT> 
                            (std::chrono::steady_clock::now() - start);
        return duration.count();
    }
};

int main() {
    std::cout << measure<>::execution(functor(dummy)) << std::endl;
}

Demo

Howard Hinnant 의 의견에 따르면 , 크로노 시스템을 벗어나지 않는 것이 가장 좋습니다. 따라서 위의 클래스는 사용자에게 count추가 정적 메소드를 제공하여 수동으로 호출하도록 선택할 수 있습니다 (C ++ 14에 표시됨)

template<typename F, typename ...Args>
static auto duration(F&& func, Args&&... args)
{
    auto start = std::chrono::steady_clock::now();
    std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
    return std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now()-start);
} 

// call .count() manually later when needed (eg IO)
auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2.0;

고객에게 가장 유용합니다.

"I / O 이전에 여러 기간을 사후 처리해야합니다 (예 : 평균)"


전체 코드는 여기에서 찾을 수 있습니다 . 크로노를 기반으로 한 벤치마킹 도구 를 구축하려는 시도 는 여기 에 기록 됩니다 .


C ++ 17 std::invoke이 사용 가능한 경우 호출 가능한 호출은 다음 execution과 같이 수행 할 수 있습니다.

invoke(forward<decltype(func)>(func), forward<Args>(args)...);

멤버 함수에 대한 포인터 인 콜 러블을 제공합니다.


2
좋은; 내 코드에는 비슷한 것이 있지만 클래스에 다른 인터페이스를 사용합니다 . 생성자에서 code_timer시작 시간 ( std::chrono::system_clock::now();) 이 걸리는 클래스 ( ) , 생성자 와 호출 code_timer::ellapsed간의 차이를 측정 하는 메서드 가 있습니다. 시작 시간을 새로운 결과 로 재설정 now()하는 code_timer::reset방법입니다 now(). 내 코드에서 functor의 실행을 측정하기 위해 클래스 외부의 무료 함수를 사용합니다. 이를 통해 객체 구성에서 비동기 호출 완료까지의 시간을 측정 할 수 있습니다.
utnapistim

7
<nitpick> :를 사용하지 않을 chrono때까지 시스템을 벗어나지 마십시오 .count(). 클라이언트 .count()가 강제로 호출 될 때 (예를 들어, 불행히도 I / O) 호출하십시오 . 클라이언트는 I / O 이전에 여러 기간 (예 : 평균)을 후 처리하고 싶을 수 있으며 이는 chrono시스템 내에서 가장 잘 수행됩니다 .
Howard Hinnant

1
@ user3241228 1. VS2013은 자동 반환 유형을 지원하지 않습니다 (후행 반환 유형-아직 사용할 수없는 c ++ 14 기능 임). 2. 나는 생각 이유입니다하지만 난 그냥 확실하게 AQ 요청
니 코스 Athanasiou

2
왜 안돼 std::forward<F>(func)?
oliora

3
@oliora 같은 것입니다. 문법적으로 존재하지 않는 std::forward<decltype(func)>(func)일반적인 람다 ( auto&& func)의 인수에 적용 할 수 있기 때문에 선호 F하며 #define fw(arg) std::forward<decltype(arg)>(arg)벤치 마크 라이브러리에서 수행 하는 유틸리티 매크로에서 쉽게 추상화 할 수 있습니다. 답변)
Nikos Athanasiou

56

귀하의 질문에서 알 수 있듯이 일부 코드 실행 후 경과 시간을 알고 싶어하는 것 같습니다. 결과를 두 번째로 편안하게 볼 수 있다고 생각합니다. 그렇다면 difftime()아래 표시된대로 기능을 사용해보십시오 . 이것이 문제를 해결하기를 바랍니다.

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

time_t start,end;
time (&start);
.
.
.
<your code>
.
.
.
time (&end);
double dif = difftime (end,start);
printf ("Elasped time is %.2lf seconds.", dif );

4
이것은 항상 정수 초를 제공합니다. 그럴까요?
질산 나트륨

10
시간은 항상 초만 반환하므로 초 단위 측정에는 사용할 수 없습니다.
DeepDeadpool

31

Windows 전용 : (이 답변을 게시 한 후 Linux 태그가 추가되었습니다)

GetTickCount () 를 사용 하여 시스템이 시작된 이후 경과 된 시간 (밀리 초 ) 을 얻을 수 있습니다 .

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();

7
나는 리눅스에서 그것을 사용하고있다. 따라서 GetTickCount () 함수를 사용할 수 없습니다.
hap497

1
이미 신경 쓰지 않습니다;) 게시물의 태그를 업데이트 해 주셔서 감사합니다
RvdK

CPU 시간이 아니라 작동하고 실시간을 제공합니다. SleepEx(5000,0)// 시간이 많이 걸리는 작업과 차이를 수행 after하고 before거의 5 초로 설정 하여 테스트했습니다 .
Ruchir

14

time(NULL)1970 년 1 월 1 일 이후 00:00에 경과 된 시간 (초)을 리턴합니다 ( Epoch ). 따라서 두 값의 차이는 처리 시간 (초)입니다.

int t0 = time(NULL);
doSomthing();
doSomthingLong();
int t1 = time(NULL);

printf ("time = %d secs\n", t1 - t0);

을 사용 getttimeofday()하면 현재 시간을 초 단위 time()와 마이크로 초 단위 로 반환하여 더 나은 결과를 얻을 수 있습니다 .


13

time (NULL) 함수는 1970 년 1 월 1 일 이후 00:00에 경과 된 시간 (초)을 반환합니다. 그리고 그 함수는 프로그램에서 다른 시간에 호출되기 때문에 C ++에서는 항상 다른 시간이됩니다


왜 누군가 다운 다운했는지 모르겠지만 귀하의 답변이 완전히 정확하지는 않습니다. 처음에는 날짜 시간을 반환하지 않으며 항상 다르지 않습니다.
Matt Joiner 2016 년

12
struct profiler
{
    std::string name;
    std::chrono::high_resolution_clock::time_point p;
    profiler(std::string const &n) :
        name(n), p(std::chrono::high_resolution_clock::now()) { }
    ~profiler()
    {
        using dura = std::chrono::duration<double>;
        auto d = std::chrono::high_resolution_clock::now() - p;
        std::cout << name << ": "
            << std::chrono::duration_cast<dura>(d).count()
            << std::endl;
    }
};

#define PROFILE_BLOCK(pbn) profiler _pfinstance(pbn)

사용법은 다음과 같습니다 ::

{
    PROFILE_BLOCK("Some time");
    // your code or function
}

이것은 범위에서 RAII와 유사합니다.

참고 이것은 내 것이 아니지만 여기에 관련이 있다고 생각했습니다.


1
누락 포함
Stepan Yakovenko

9
#include<time.h> // for clock
#include<math.h> // for fmod
#include<cstdlib> //for system
#include <stdio.h> //for delay

using namespace std;

int main()
{


   clock_t t1,t2;

   t1=clock(); // first time capture

   // Now your time spanning loop or code goes here
   // i am first trying to display time elapsed every time loop runs

   int ddays=0; // d prefix is just to say that this variable will be used for display
   int dhh=0;
   int dmm=0;
   int dss=0;

   int loopcount = 1000 ; // just for demo your loop will be different of course

   for(float count=1;count<loopcount;count++)
   {

     t2=clock(); // we get the time now

     float difference= (((float)t2)-((float)t1)); // gives the time elapsed since t1 in milliseconds

    // now get the time elapsed in seconds

    float seconds = difference/1000; // float value of seconds
    if (seconds<(60*60*24)) // a day is not over
    {
        dss = fmod(seconds,60); // the remainder is seconds to be displayed
        float minutes= seconds/60;  // the total minutes in float
        dmm= fmod(minutes,60);  // the remainder are minutes to be displayed
        float hours= minutes/60; // the total hours in float
        dhh= hours;  // the hours to be displayed
        ddays=0;
    }
    else // we have reached the counting of days
    {
        float days = seconds/(24*60*60);
        ddays = (int)(days);
        float minutes= seconds/60;  // the total minutes in float
        dmm= fmod(minutes,60);  // the rmainder are minutes to be displayed
        float hours= minutes/60; // the total hours in float
        dhh= fmod (hours,24);  // the hours to be displayed

    }

    cout<<"Count Is : "<<count<<"Time Elapsed : "<<ddays<<" Days "<<dhh<<" hrs "<<dmm<<" mins "<<dss<<" secs";


    // the actual working code here,I have just put a delay function
    delay(1000);
    system("cls");

 } // end for loop

}// end of main 

3
귀하의 답변에 감사하지만 코드에 대한 간단한 설명이 포함 된 프리앰블을 선호합니다. 감사.
Kev

2
이것은 경과 시간이 아니라 프로세서 시간입니다.
JonnyJD

8

두 번째 프로그램이 인쇄 한 값은 초와 마이크로 초입니다.

0 26339 = 0.026'339 s =   26339 µs
4 45025 = 4.045'025 s = 4045025 µs

8
#include <ctime>
#include <cstdio>
#include <iostream>
#include <chrono>
#include <sys/time.h>
using namespace std;
using namespace std::chrono;

void f1()
{
  high_resolution_clock::time_point t1 = high_resolution_clock::now();
  high_resolution_clock::time_point t2 = high_resolution_clock::now();
  double dif = duration_cast<nanoseconds>( t2 - t1 ).count();
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f2()
{
  timespec ts1,ts2;
  clock_gettime(CLOCK_REALTIME, &ts1);
  clock_gettime(CLOCK_REALTIME, &ts2);
  double dif = double( ts2.tv_nsec - ts1.tv_nsec );
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f3()
{
  struct timeval t1,t0;
  gettimeofday(&t0, 0);
  gettimeofday(&t1, 0);
  double dif = double( (t1.tv_usec-t0.tv_usec)*1000);
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}
void f4()
{
  high_resolution_clock::time_point t1 , t2;
  double diff = 0;
  t1 = high_resolution_clock::now() ;
  for(int i = 1; i <= 10 ; i++)
  {
    t2 = high_resolution_clock::now() ;
    diff+= duration_cast<nanoseconds>( t2 - t1 ).count();
    t1 = t2;
  }
  printf ("high_resolution_clock:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f5()
{
  timespec ts1,ts2;
  double diff = 0;
  clock_gettime(CLOCK_REALTIME, &ts1);
  for(int i = 1; i <= 10 ; i++)
  {
    clock_gettime(CLOCK_REALTIME, &ts2);
    diff+= double( ts2.tv_nsec - ts1.tv_nsec );
    ts1 = ts2;
  }
  printf ("clock_gettime:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f6()
{
  struct timeval t1,t2;
  double diff = 0;
  gettimeofday(&t1, 0);
  for(int i = 1; i <= 10 ; i++)
  {
    gettimeofday(&t2, 0);
    diff+= double( (t2.tv_usec-t1.tv_usec)*1000);
    t1 = t2;
  }
  printf ("gettimeofday:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

int main()
{
  //  f1();
  //  f2();
  //  f3();
  f6();
  f4();
  f5();
  return 0;
}

4

C ++ std :: chrono는 크로스 플랫폼이라는 확실한 이점이 있습니다. 그러나 POSIX clock_gettime ()에 비해 상당한 오버 헤드가 발생합니다. 내 리눅스 박스에서 모든 std::chrono::xxx_clock::now()맛은 거의 동일합니다.

std::chrono::system_clock::now()
std::chrono::steady_clock::now()
std::chrono::high_resolution_clock::now()

POSIX clock_gettime(CLOCK_MONOTONIC, &time)는 동일해야 steady_clock::now()하지만 x3 배 이상 빠릅니다!

여기 내 완성도 테스트가 있습니다.

#include <stdio.h>
#include <chrono>
#include <ctime>

void print_timediff(const char* prefix, const struct timespec& start, const 
struct timespec& end)
{
    double milliseconds = end.tv_nsec >= start.tv_nsec
                        ? (end.tv_nsec - start.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec) * 1e3
                        : (start.tv_nsec - end.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec - 1) * 1e3;
    printf("%s: %lf milliseconds\n", prefix, milliseconds);
}

int main()
{
    int i, n = 1000000;
    struct timespec start, end;

    // Test stopwatch
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i) {
        struct timespec dummy;
        clock_gettime(CLOCK_MONOTONIC, &dummy);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("clock_gettime", start, end);

    // Test chrono system_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::system_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::system_clock::now", start, end);

    // Test chrono steady_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::steady_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::steady_clock::now", start, end);

    // Test chrono high_resolution_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::high_resolution_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::high_resolution_clock::now", start, end);

    return 0;
}

그리고 이것은 gcc7.2 -O3으로 컴파일 할 때 얻는 결과입니다.

clock_gettime: 24.484926 milliseconds
chrono::system_clock::now: 85.142108 milliseconds
chrono::steady_clock::now: 87.295347 milliseconds
chrono::high_resolution_clock::now: 84.437838 milliseconds

3

time(NULL)두 시간 소인의 차이를 취 할 말은 아마도 어떤 1월 1일 1970 : 초 수를 반환합니다 함수 호출은 EPOC 경과 :

size_t start = time(NULL);
doSomthing();
doSomthingLong();

printf ("**MyProgram::time elapsed= %lds\n", time(NULL) - start);

3

다른 사람들이 이미 언급했듯이 C 표준 라이브러리의 time () 함수는 1 초보다 나은 해상도를 가지고 있지 않습니다. 더 나은 해상도를 제공 할 수있는 완전 휴대용 C 함수는 clock () 인 것처럼 보이지만 벽시계 시간보다는 프로세서 시간을 측정합니다. POSIX 플랫폼 (예 : Linux)으로 자신을 제한하는 내용이라면 clock_gettime () 함수를 사용하는 것이 좋습니다.

C ++ 11부터는 다른 컴파일러와 운영 체제에서 이식성이 뛰어난 형태로 더 나은 해상도를 제공하는 훨씬 더 나은 타이밍 기능이 있습니다. 마찬가지로 boost :: datetime 라이브러리는 이식성이 뛰어난 우수한 타이밍 클래스를 제공합니다.

이러한 기능을 사용하는 데있어 한 가지 과제는 시스템 시계를 쿼리하여 발생하는 시간 지연입니다. clock_gettime (), boost :: datetime 및 std :: chrono 실험 에서이 지연은 마이크로 초의 문제 일 수 있습니다. 따라서 코드 일부의 지속 시간을 측정 할 때는이 크기 정도의 측정 오류가 발생하도록하거나 어떤 방식 으로든 제로 오류를 수정해야합니다. 이상적으로는 함수가 수행 한 시간의 여러 측정 값을 수집하고 여러 실행에서 걸리는 평균 또는 최대 / 최소 시간을 계산할 수 있습니다.

이러한 모든 이식성 및 통계 수집 문제를 돕기 위해 Github에서 사용할 수있는 cxx-rtimers 라이브러리를 개발하여 C ++ 코드의 타이밍 블록, 제로 오류 계산 및 여러 타이머에 내장 된 통계보고를위한 간단한 API를 제공하려고합니다. 귀하의 코드에서. C ++ 11 컴파일러가 있다면 간단하게 #include <rtimers/cxx11.hpp>다음과 같은 것을 사용하십시오.

void expensiveFunction() {
    static rtimers::cxx11::DefaultTimer timer("expensiveFunc");
    auto scopedStartStop = timer.scopedStart();
    // Do something costly...
}

프로그램 종료시 다음과 같이 std :: cerr에 기록 된 타이밍 통계에 대한 요약을 얻을 수 있습니다.

Timer(expensiveFunc): <t> = 6.65289us, std = 3.91685us, 3.842us <= t <= 63.257us (n=731)

평균 시간, 표준 편차, 상한 및 하한 및이 함수가 호출 된 횟수를 보여줍니다.

Linux 특정 타이밍 함수를 사용하려는 경우 #include <rtimers/posix.hpp>또는 Boost 라이브러리가 있지만 이전 C ++ 컴파일러가있는 경우 다음을 수행 할 수 있습니다 #include <rtimers/boost.hpp>. 여러 스레드에서 통계적 타이밍 정보를 수집 할 수있는 이러한 타이머 클래스 버전도 있습니다. 시스템 시계의 2 개의 연속 연속 쿼리와 관련된 제로 오류를 추정 할 수있는 방법도 있습니다.


2

내부적으로 함수는 시스템의 시계에 액세스하므로 호출 할 때마다 다른 값을 반환합니다. 비 기능 언어에서는 일반적으로 함수의 이름과 인수를 보면 볼 수없는 많은 부작용과 숨겨진 상태가 함수에있을 수 있습니다.


2

tv_sec은 경과 시간 (초)을 저장하고 tv_usec는 경과 시간 (마이크로 초)을 별도로 표시합니다. 그리고 그들은 서로의 전환이 아닙니다. 따라서 총 시간이 경과하도록 적절한 단위로 변경하고 추가해야합니다.

struct timeval startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

printf("**time taken in microseconds = %ld\n",
    (endTV.tv_sec * 1e6 + endTV.tv_usec - (startTV.tv_sec * 1e6 + startTV.tv_usec))
    );

2

리눅스에서 clock_gettime ()은 좋은 선택 중 하나입니다. 실시간 라이브러리 (-lrt)를 연결해야합니다.

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

#define BILLION  1000000000L;

int main( int argc, char **argv )
  {
    struct timespec start, stop;
    double accum;

    if( clock_gettime( CLOCK_REALTIME, &start) == -1 ) {
      perror( "clock gettime" );
      exit( EXIT_FAILURE );
    }

    system( argv[1] );

    if( clock_gettime( CLOCK_REALTIME, &stop) == -1 ) {
      perror( "clock gettime" );
      exit( EXIT_FAILURE );
    }

    accum = ( stop.tv_sec - start.tv_sec )
          + ( stop.tv_nsec - start.tv_nsec )
            / BILLION;
    printf( "%lf\n", accum );
    return( EXIT_SUCCESS );
  }

2

라이브러리 내에서 개별 함수의 실행 시간을 측정해야했습니다. 모든 기능의 모든 호출을 시간 측정 기능으로 감싸고 싶지는 않았습니다. 왜냐하면 콜 스택이 추악하기 때문입니다. 또한 타이머 코드를 모든 함수의 맨 위와 맨 아래에 배치하고 싶지 않았습니다. 예를 들어 함수가 일찍 종료되거나 예외를 던질 때 엉망이되기 때문입니다. 그래서 내가 한 일은 자신의 수명을 사용하여 시간을 측정하는 타이머를 만드는 것이 었습니다.

이 방법으로 문제의 코드 블록 시작 부분에서 이러한 객체 중 하나를 인스턴스화하고 (실제로 범위 또는 실제 범위) 인스턴스 소멸자가 이후에 경과 한 시간을 측정 할 수있게함으로써 코드 블록의 소요 시간을 측정 할 수 있습니다 인스턴스가 범위를 벗어날 때 구성. 당신은 전체 예제를 찾을 수 있습니다 여기에 있지만 구조체는 매우 간단하다 :

template <typename clock_t = std::chrono::steady_clock>
struct scoped_timer {
  using duration_t = typename clock_t::duration;
  const std::function<void(const duration_t&)> callback;
  const std::chrono::time_point<clock_t> start;

  scoped_timer(const std::function<void(const duration_t&)>& finished_callback) :
      callback(finished_callback), start(clock_t::now()) { }
  scoped_timer(std::function<void(const duration_t&)>&& finished_callback) :
      callback(finished_callback), start(clock_t::now()) { }
  ~scoped_timer() { callback(clock_t::now() - start); }
};

struct는 범위를 벗어나면 제공된 functor를 호출하여 타이밍 정보로 무언가를 할 수 있습니다 (인쇄 또는 저장 등). 더 복잡한 것을 해야하는 경우 더 많은 인수로 함수를 콜백 std::bind하는 std::placeholders데 사용할 수도 있습니다 .

다음은이를 사용하는 간단한 예입니다.

void test(bool should_throw) {
  scoped_timer<> t([](const scoped_timer<>::duration_t& elapsed) {
    auto e = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(elapsed).count();
    std::cout << "took " << e << "ms" << std::endl;
  });

  std::this_thread::sleep_for(std::chrono::seconds(1));

  if (should_throw)
    throw nullptr;

  std::this_thread::sleep_for(std::chrono::seconds(1));
}

좀 더 고의가되고 싶다면, 범위 지정에 의존하지 않고 타이머를 사용 new하고 delete명시 적으로 시작 및 중지 할 수도 있습니다.


1

doSomething 함수가 타이머의 세분성보다 빠르기 때문에 동일합니다. 시험:

printf ("**MyProgram::before time= %ld\n", time(NULL));

for(i = 0; i < 1000; ++i) {
    doSomthing();
    doSomthingLong();
}

printf ("**MyProgram::after time= %ld\n", time(NULL));

1

두 값이 동일한 이유는 긴 프로 시저 가 1 초 미만으로 오래 걸리지 않기 때문 입니다. 함수의 끝에 긴 루프 (for (int i = 0; i <100000000; i ++);)를 추가하여 이것이 문제인지 확인한 다음 거기에서 갈 수 있습니다 ...

위의 내용이 사실로 밝혀지면 시간을보다 정확하게 측정하기 위해 다른 시스템 기능을 찾아야합니다 (리눅스에서 작업한다는 것을 이해하므로 함수 이름으로 도울 수 없습니다). 리눅스에는 GetTickCount ()와 비슷한 기능이 있다고 확신합니다.


1

나는 보통 다음을 사용합니다.

#include <chrono>
#include <type_traits>

using perf_clock = std::conditional<
    std::chrono::high_resolution_clock::is_steady,
    std::chrono::high_resolution_clock,
    std::chrono::steady_clock
>::type;

using floating_seconds = std::chrono::duration<double>;

template<class F, class... Args>
floating_seconds run_test(Func&& func, Args&&... args)
{
   const auto t0 = perf_clock::now();
   std::forward<Func>(func)(std::forward<Args>(args)...);
   return floating_seconds(perf_clock::now() - t0);
} 

비 안정 시계 사용을 피하고 부동 초 수를 지속 시간으로 사용한다는 점을 제외하고 @ nikos-athanasiou가 제안한 것과 동일합니다.


1
유형 스위치에서 : 일반적으로 또는에 high_resolution_clock대한 typedef입니다 . 그래서 추적하는 경우 생성 부분은 사실, 당신은 선택 이다 (에 대한 형식 정의)이를 . 틀린 경우 다시 선택 하십시오. 처음부터 사용 하십시오 ...system_clocksteady_clockstd::conditionalis_steadyhigh_resolution_clocksteady_clocksteady_clocksteady_clock
Nikos Athanasiou

@ nikos-athanasiou 나는 5gon12eder의 의견에 전적으로 동의합니다. 표준에는 "일반적인"사례가 필요하지 않으므로 일부 STL은 다른 방식으로 구현 될 수 있습니다. 내 코드를보다 일반적이고 구현 세부 사항과 관련이없는 것을 선호합니다.
oliora

그것은 필요하지만 명시 적으로 언급 아니에요 20.12.7.3 : high_resolution_clock may be a synonym for system_clock or steady_clock. 이유는 이것입니다 : high_resolution_clock틱 기간이 가장 짧은 시계를 나타내므로 구현에 관계없이 꾸준한 지 아닌지 두 가지 선택이 있습니다. 우리가 무엇을 선택하든 구현이 다른 두 클럭과 다를 것이라고 말하는 것은 사용하지 않기로 선택한 꾸준한 (또는 꾸준하지 않은) 클럭에 대해 더 나은 구현이 있다고 말하는 것과 같습니다. 어떻게 좋은지, 왜 좋은지 알기
Nikos Athanasiou

@ nikos-athanasiou 나는 특히 런타임 오버 헤드와 감지 할 수없는 컴파일 시간 오버 헤드가 들지 않을 때 100 % 안전을 선호합니다. 원하는 경우 "may"및 암살에 의존 할 수 있습니다.
oliora

au는 내 친구를 모순한다. "may"에 의존하지만 자신에게 맞는 것은 당신이다. 100 % 확실하고이를 계속 작성하려면 코드를 사용하는 사용자와 사용자가 서로 다른 클럭의 시점을 비 혼합 적으로 혼합하는 것을 피할 수있는 방법을 찾아야합니다 (이 유형 스위치가 의미를 얻는 경우, 플랫폼마다 다르게 작동합니다). 즐기세요!
Nikos Athanasiou

0

OP의 세 가지 특정 질문에 대한 답변.

"이전과 이후의 값이 같은 이유는 무엇입니까? "

번째 질문 과 샘플 코드는 time()1 초의 해상도를 가짐을 보여 주므로 두 함수가 1 초 이내에 실행되어야합니다. 그러나 때로는 두 타이머 표시가 1 초 경계에 걸리면 (명백하게 비논리적으로) 1 초를 알립니다 .

다음 예제는 gettimeofday()이 구조체를 채우는 사용합니다.

struct timeval {
    time_t      tv_sec;     /* seconds */
    suseconds_t tv_usec;    /* microseconds */
};

그리고 두 번째 질문은 묻습니다 : "어떻게 결과 읽습니까 **time taken = 0 26339않습니다 평균 26,339 나노초 = 26.3 밀리 초를?"

내 두 번째 대답은 걸리는 시간이 0 초와 26339 마이크로 초, 즉 0.026339 초이며, 첫 번째 예제는 1 초 미만으로 실행됩니다.

세 번째 질문은 묻습니다 : "무엇에 대해 **time taken = 4 45025, 그 평균 사초 25 밀리 초를합니까?"

세 번째 답변은 소요 시간이 4 초와 45025 마이크로 초, 즉 4.045025 초이며, 이는 OP가 이전에 시간을 정한 두 기능에 의해 수행 된 작업을 변경했음을 보여줍니다.


0
#include <ctime>
#include <functional>

using namespace std;

void f() {
  clock_t begin = clock();

  // ...code to measure time...

  clock_t end = clock();

  function<double(double, double)> convtime = [](clock_t begin, clock_t end)
  {
     return double(end - begin) / CLOCKS_PER_SEC;
  };

  printf("Elapsed time: %.2g sec\n", convtime(begin, end));

}

여기에 사용 가능한 것과 유사한 예제가 있으며 추가 변환 기능 + 인쇄 만 있습니다.


0

경과 시간을 자동으로 측정하는 클래스를 만들었습니다. https://github.com/sonnt174/Common/blob/master/time_measure.h 링크에서 코드 (c ++ 11)를 확인하십시오.

TimeMeasure 클래스를 사용하는 방법의 예 :

void test_time_measure(std::vector<int> arr) {
  TimeMeasure<chrono::microseconds> time_mea;  // create time measure obj
  std::sort(begin(arr), end(arr));
}

나는 당신의 단위와 함께 당신의 인쇄 명세서를 좋아한다. 코드를 gcc와 clang으로 포팅하는 데 무엇이 필요할까요? ( wandbox.org )
Howard Hinnant

1
@HowardHinnant : 주소 지정에 감사드립니다 .gcc 및 clang의 코드도 업데이트했습니다.
Sirn Nguyen Truong

0

Matlab 맛!

tic스톱워치 타이머를 시작하여 성능을 측정합니다. 이 함수는 tic 명령 실행시 내부 시간을 기록합니다. toc기능 과 함께 경과 시간을 표시합니다 .

#include <iostream>
#include <ctime>
#include <thread>
using namespace std;

clock_t START_TIMER;

clock_t tic()
{
    return START_TIMER = clock();
}

void toc(clock_t start = START_TIMER)
{
    cout
        << "Elapsed time: "
        << (clock() - start) / (double)CLOCKS_PER_SEC << "s"
        << endl;
}

int main()
{
    tic();
    this_thread::sleep_for(2s);
    toc();

    return 0;
}

-4

단순하고 빠른 멀티미디어 라이브러리 인 SFML 라이브러리 를 사용할 수 있습니다 . Clock, Socket, Sound, Graphics 등과 같이 유용하고 잘 정의 된 많은 클래스가 포함되어 있습니다. 사용하기 쉽고 강력하게 권장됩니다.

이것이이 질문의 예입니다.

sf::Clock clock;
...
Time time1 = clock.getElapsedTime();
...
Time time2 = clock.restart();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.