Linux에서 C ++가 밀리 초 시간을 가져옴 — clock ()이 제대로 작동하지 않는 것 같습니다.


102

Windows에서는 clock()시간을 밀리 초 단위로 반환하지만 제가 작업중인이 Linux 상자에서는 가장 가까운 1000으로 반올림하여 정밀도가 밀리 초 수준이 아닌 "초"수준으로 만 표시됩니다.

QTime클래스를 사용하여 Qt로 솔루션을 찾고 객체를 인스턴스화하고 호출 start()한 다음 elapsed()밀리 초 경과 시간을 가져 오기 위해 호출 했습니다.

처음에는 Qt로 작업하고 있기 때문에 운이 좋았지 만 타사 라이브러리에 의존하지 않는 솔루션을 원합니다.

이를 수행하는 표준 방법이 없습니까?

최신 정보

Boost .. 추천하지 마세요.

Boost와 Qt가 그것을 할 수 있다면 확실히 마술이 아닙니다. 그들이 사용하는 표준이 있어야합니다!


2
편집에 대해-그러나 휴대용 방식으로 수행하는 것은 약간의 고통입니다.
Anonymous

답변:


37

메서드의 시작과 끝에서 gettimeofday를 사용한 다음 두 반환 구조체를 구분할 수 있습니다. 다음과 같은 구조를 얻게됩니다.

struct timeval {
  time_t tv_sec;
  suseconds_t tv_usec;
}

편집 : 아래의 두 의견에서 알 수 있듯이 clock_gettime (CLOCK_MONOTONIC)은 사용 가능한 경우 훨씬 더 나은 선택이며 요즘 거의 모든 곳에 있어야합니다.

편집 : 다른 사람은 std :: chrono :: high_resolution_clock과 함께 최신 C ++를 사용할 수도 있다고 언급했지만 단조롭다는 보장은 없습니다. 대신 steady_clock을 사용하십시오.


38
진지한 일에 끔찍합니다. 누군가가 데이트를 할 때 일 년에 두 번 큰 문제가 발생하고 물론 NTP가 동기화됩니다. clock_gettime (CLOCK_MONOTONIC,) 사용
AndrewStone 2011-06-19

9
@AndrewStone : UNIX 시간은 1 년에 두 번 변경되지 않습니다. 또는 1 년에 한 번. 그러나 예, CLOCK_MONOTONIC현지화 된 시스템 시간 조정을 피하는 데 좋습니다.
궤도의 경쾌한 레이스

138
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
    struct timeval start, end;

    long mtime, seconds, useconds;    

    gettimeofday(&start, NULL);
    usleep(2000);
    gettimeofday(&end, NULL);

    seconds  = end.tv_sec  - start.tv_sec;
    useconds = end.tv_usec - start.tv_usec;

    mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;

    printf("Elapsed time: %ld milliseconds\n", mtime);

    return 0;
}

4
왜 차이에 +0.5를 더합니까?
Mahmoud Al-Qudsi

19
@Computer Guru, 양수 값을 반올림하는 일반적인 기술입니다. 값이 정수 값으로 잘 리면 0.0에서 0.4999 사이 ... 더하기 전에는 0으로 잘리고 0.5에서 0.9999 사이는 1로 잘립니다.
Mark Ransom

8
tv_usec는 밀리 초가 아니라 마이크로 초입니다.
NebulaFox 2011

13
진지한 일에 끔찍합니다. 누군가가 데이트를 할 때 일 년에 두 번 큰 문제와 NTP 동기화
AndrewStone 2011-06-19

14
@AndrewStone이 맞습니다. clock_gettime (2)을 CLOCK_REALTIME과 함께 사용하여 동일한 컴퓨터의 시간을 비교하십시오. 은 gettimeofday에서 (2) 맨 : POSIX.1-2008 marks gettimeofday() as obsolete, recommending the use of clock_gettime(2) instead. @CTT, 당신은을 변경하여 예를 업데이트 할 수 있습니다 struct timevalstruct timespec, 그리고 gettimeofday(&start, NULL)clock_gettime(CLOCK_MONOTONIC, &start)그 사람들이 문제로 실행하지 않도록?
Bobby Powers

58

벽시계 시간 clock은 측정 하지 않으므로 양해 바랍니다 . 즉, 프로그램에 5 초가 걸리면 clock반드시 5 초를 측정하지는 않지만 더 많을 수 있습니다 (프로그램이 여러 스레드를 실행할 수 있으므로 실시간보다 더 많은 CPU를 소비 할 수 있음). 사용 된 CPU 시간 의 근사치를 측정합니다 . 차이점을 확인하려면이 코드를 고려하십시오.

#include <iostream>
#include <ctime>
#include <unistd.h>

int main() {
    std::clock_t a = std::clock();
    sleep(5); // sleep 5s
    std::clock_t b = std::clock();

    std::cout << "difference: " << (b - a) << std::endl;
    return 0;
}

내 시스템에 출력

$ difference: 0

왜냐하면 우리가 한 것은 CPU 시간을 사용하지 않고 잠자기 때문입니다! 그러나 gettimeofday우리는 우리가 원하는 것을 얻습니다 (?)

#include <iostream>
#include <ctime>
#include <unistd.h>
#include <sys/time.h>

int main() {
    timeval a;
    timeval b;

    gettimeofday(&a, 0);
    sleep(5); // sleep 5s
    gettimeofday(&b, 0);

    std::cout << "difference: " << (b.tv_sec - a.tv_sec) << std::endl;
    return 0;
}

내 시스템의 출력

$ difference: 5

더 많은 정밀도가 필요하지만 CPU 시간 을 얻으려면 getrusage함수 사용을 고려할 수 있습니다 .


⁺¹ 언급 a에 대해 sleep()— 귀하의 답변을 찾았을 때 이미 질문을 할 생각입니다 (왜 저를 제외한 모든 사람에게 잘 작동합니까?!) .
Hi-Angel

18

Boost에서 제공하는 도구도 추천합니다. 언급 된 Boost Timer 또는 Boost.DateTime에서 무언가를 해킹하거나 샌드 박스에 새로 제안 된 라이브러리 가 있습니다 -Boost.Chrono :이 마지막 것은 Timer를 대체하며 다음과 같은 기능을 제공합니다.

  • 다음을 포함한 C ++ 0x 표준 라이브러리의 시간 유틸리티 :
    • 클래스 템플릿 duration
    • 클래스 템플릿 time_point
    • 시계 :
      • system_clock
      • monotonic_clock
      • high_resolution_clock
  • timertypedef가있는 클래스 템플릿 :
    • system_timer
    • monotonic_timer
    • high_resolution_timer
  • 프로세스 클록 및 타이머 :
    • process_clock, 실제, 사용자 CPU 및 시스템 CPU 시간을 캡처합니다.
    • process_timer, 경과 된 실제, 사용자 CPU 및 시스템 CPU 시간을 캡처합니다.
    • run_timer, | process_timer |의 편리한보고 결과.
  • C ++ 0x 표준 라이브러리의 컴파일 시간 합리적 산술.

기능 목록 의 출처다음과 같습니다.


지금은 부스트 ​​타이머를 사용하고 검토 / 승인을 받으면 Chrono로 정상적으로 마이그레이션 할 수 있습니다.
Anonymous

13

CTT의 답변을Timer 기반으로 수업을 작성했습니다 . 다음과 같은 방법으로 사용할 수 있습니다.

Timer timer = Timer();
timer.start();
/* perform task */
double duration = timer.stop();
timer.printTime(duration);

구현은 다음과 같습니다.

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
using namespace std;

class Timer {
private:

    timeval startTime;

public:

    void start(){
        gettimeofday(&startTime, NULL);
    }

    double stop(){
        timeval endTime;
        long seconds, useconds;
        double duration;

        gettimeofday(&endTime, NULL);

        seconds  = endTime.tv_sec  - startTime.tv_sec;
        useconds = endTime.tv_usec - startTime.tv_usec;

        duration = seconds + useconds/1000000.0;

        return duration;
    }

    static void printTime(double duration){
        printf("%5.6f seconds\n", duration);
    }
};

2
이것은 멋지지만 "nseconds"는 timeval이 나노초를 보유하지 않고 마이크로 초를 보유하기 때문에 오해의 소지가 있습니다. 그래서 사람들이 이것을 "useconds"라고 부르도록 제안합니다.
pho0

감사. 수정되었습니다.
Chris Redford 2012

9

코드를 이전 유니스로 이식 할 필요가없는 경우 clock_gettime ()을 사용하여 나노초 단위로 시간을 제공 할 수 있습니다 (프로세서가 해당 해상도를 지원하는 경우). POSIX이지만 2001 년부터.


4

clock ()은 종종 꽤 형편없는 해상도를 가지고 있습니다. 밀리 초 수준에서 시간을 측정하려면 이 질문에 설명 된 대로 clock_gettime ()을 사용하는 방법이 있습니다 .

(Linux에서는 -lrt와 링크해야합니다.)


4

C ++ 11을 사용 std::chrono::high_resolution_clock하면 다음을 수행 할 수 있습니다.

#include <iostream>
#include <chrono>
#include <thread>
typedef std::chrono::high_resolution_clock Clock;

int main()
{
    std::chrono::milliseconds three_milliseconds{3};

    auto t1 = Clock::now();
    std::this_thread::sleep_for(three_milliseconds);
    auto t2 = Clock::now();

    std::cout << "Delta t2-t1: " 
              << std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count()
              << " milliseconds" << std::endl;
}

산출:

Delta t2-t1: 3 milliseconds

데모 링크 : http://cpp.sh/2zdtu


2

clock ()은 Linux에서 밀리 초 또는 초를 반환하지 않습니다. 일반적으로 clock ()은 리눅스 시스템에서 마이크로 초를 반환합니다. clock ()에 의해 반환 된 값을 해석하는 적절한 방법은 CLOCKS_PER_SEC로 나누어 시간이 얼마나 경과했는지 알아내는 것입니다.


내가 작업하고있는 상자가 아니라! 플러스, 내가 하고 CLOCKS_PER_SEC로 나누어,하지만 해상도는 아래 두 번째에 있기 때문에 그것은 무의미
하센

공정하게 말하면 단위 마이크로 초입니다 (CLOCKS_PER_SEC는 모든 POSIX 시스템에서 1000000 임). 초 해상도가 있습니다. :-피.
Evan Teran

1

이것은 작동합니다 ... Mac에서 테스트되었습니다 ...

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

int main() {
        struct timeval tv;
        struct timezone tz;
        struct tm *tm;
        gettimeofday(&tv,&tz);
        tm=localtime(&tv.tv_sec);
        printf("StartTime: %d:%02d:%02d %d \n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec);
}

네 ... 두 번 실행하고 빼기 ...


1

POSIX 표준 clock에서 반환 값은 CLOCKS_PER_SEC 기호로 정의되며 구현은이를 편리한 방식으로 자유롭게 정의 할 수 있습니다. Linux에서 나는 그 times()기능에 행운을 빕니다 .


1

gettimeofday-문제는 하드웨어 클럭 (예 : NTP 사용)을 변경하면 더 낮은 값을 가질 수 있다는 것입니다. Boost-이 프로젝트에서는 사용할 수 없음 clock ()-일반적으로 4 바이트 정수를 반환합니다. 얼마 후 음수를 반환합니다.

나는 내 자신의 수업을 만들고 매 10 밀리 초마다 업데이트하는 것을 선호한다. 그래서이 방법이 더 유연하고 구독자를 가지도록 개선 할 수도있다.

class MyAlarm {
static int64_t tiempo;
static bool running;
public:
static int64_t getTime() {return tiempo;};
static void callback( int sig){
    if(running){
        tiempo+=10L;
    }
}
static void run(){ running = true;}
};

int64_t MyAlarm::tiempo = 0L;
bool MyAlarm::running = false;

새로 고침하려면 setitimer를 사용합니다.

int main(){
struct sigaction sa; 
struct itimerval timer; 

MyAlarm::run();
memset (&sa, 0, sizeof (sa)); 
sa.sa_handler = &MyAlarm::callback; 

sigaction (SIGALRM, &sa, NULL); 


timer.it_value.tv_sec = 0; 
timer.it_value.tv_usec = 10000; 



timer.it_interval.tv_sec = 0; 
timer.it_interval.tv_usec = 10000; 


setitimer (ITIMER_REAL, &timer, NULL); 
.....

setitimer와 ITIMER_VIRTUAL 및 ITIMER_REAL을보십시오.

알람 또는 ualarm 기능을 사용하지 마십시오. 공정이 힘들 때 정밀도가 떨어집니다.



0

업데이트로 Windows clock ()에서 벽시계 시간 (CLOCKS_PER_SEC 정밀도 사용)을 측정하는 것으로 나타납니다.

 http://msdn.microsoft.com/en-us/library/4e2ess30(VS.71).aspx

Linux에서는 현재 프로세스에서 사용하는 코어에서 CPU 시간을 측정합니다.

http://www.manpagez.com/man/3/clock

그리고 (나타나고, 원래 포스터에서 언급했듯이) 실제로 CLOCKS_PER_SEC 보다 정밀도가 낮지 만 특정 버전의 Linux에 따라 다를 수 있습니다.


0

나는 gettimeofday ()를 사용하지 않는 Hola Soy 방법을 좋아합니다. 실행중인 서버에서 관리자가 시간대를 변경했습니다. 시계가 동일한 (올바른) 로컬 값을 표시하도록 업데이트되었습니다. 이로 인해 time () 및 gettimeofday () 함수가 2 시간 이동하고 일부 서비스의 모든 타임 스탬프가 중단되었습니다.


0

내가 쓴 C++사용하여 클래스를 timeb.

#include <sys/timeb.h>
class msTimer 
{
public:
    msTimer();
    void restart();
    float elapsedMs();
private:
    timeb t_start;
};

회원 기능 :

msTimer::msTimer() 
{ 
    restart(); 
}

void msTimer::restart() 
{ 
    ftime(&t_start); 
}

float msTimer::elapsedMs() 
{
    timeb t_now;
    ftime(&t_now);
    return (float)(t_now.time - t_start.time) * 1000.0f +
           (float)(t_now.millitm - t_start.millitm);
}

사용 예 :

#include <cstdlib>
#include <iostream>

using namespace std;

int main(int argc, char** argv) 
{
    msTimer t;
    for (int i = 0; i < 5000000; i++)
        ;
    std::cout << t.elapsedMs() << endl;
    return 0;
}

내 컴퓨터의 출력은 '19'입니다. msTimer클래스의 정확도는 밀리 초 정도입니다. 위의 사용 예에서는 for루프가 차지하는 총 실행 시간 이 추적됩니다. 이 시간에는 main()멀티 태스킹으로 인해 실행 컨텍스트를 전환하는 운영 체제가 포함되었습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.