[C언어/C++] 정밀한 시간 측정 (clock, getTickcount, timeGetTime) 함수의 차이와 사용법

    C언어나 C++에서 제공하고 있는 시간을 측정하는 함수들이 많이 있습니다. 그중에서는 time함수도 있습니다. 하지만 time함수의 경우 시간을 초(s) 단위 측정까지만 가능하므로 정밀한 시간측정에는 부적합한 함수 입니다.

    [C언어/C++] 현재 날짜/시간 원하는 형태로 출력하기 (time, localtime)

     

    정밀한 시간 측정하기

    어떻게 하면 컴퓨터에서 정밀한 시간을 측정할 수 있을까요? 사실 C언어나 C++같은 프로그래밍 언어에서 시간을 측정할 수 있는 기능을 제공하는 것은 아닙니다. 시간을 측정한다는것 자체가 OS의 힘을 빌려야만 가능합니다. 윈도우에서 여러가지 시간을 측정할 수 있는 함수들을 만들어놓고 그것을 C언어나 C++같은 프로그래밍 언어에서 그대로 가져다 쓰는것 뿐입니다.

     

    그렇다면 OS에서는 시간을 어떻게 측정할까요? 컴퓨터는 내부적으로 시간을 측정하기 위해서 타이머 / 카운터를 사용합니다. 마이크로컨트롤러에서 타이머/카운터는 일정한 개수만큼 클럭을 세어 정해진 시간이 되면 인터럽트를 발생시키는 역할을 하게 됩니다. 

     

    컴퓨터 시간측정 방법

    주기 : 0과 1이 번갈아 한번 나타나는 시간

    주파수 : 1초당 몇번이나 0과 1이 변화하였는가?

     

    디지털 회로에서 클록은 주어진 일을 순서대로 정확한 시간에 처리하기 위해 사용됩니다. 클록은 시계의 역할을 하며, 일정한 시간간격으로 0과 1의 값이 번갈아 가게 나타나게 되어있습니다. 그리고 카운터는 이 클록을 세는 역할을 합니다. 클록이 하나 발생 (즉, 0과 1이 한번 변경)할때마다 카운터가 1씩 증가됩니다. 이것으로 컴퓨터가 시간을 측정합니다. 이렇게 측정한 시간을 OS에서 함수로 만들어 프로그래밍 언어에 제공하는것입니다. C언어, C++에서는 대표적으로 clock()함수, getTiccount()함수, getTiccount64(), timeGetTime()함수가 있습니다. 해당 함수들은 시간을 밀리초 단위까지 연산합니다. 세밀한 시간측정이 필요하다면 위의 함수를 사용하여야 합니다.

    [수학] 초 단위 종류 (극 미세 시간) + 변환 사이트

     

    clock 함수 사용법

    #include <iostream>
    #include <time.h> //clock함수가 있는 헤더
    
    using namespace std;
    void main()
    {
        for (;;) {
            clock_t time = clock();
            double timeSecond = (double)(time / CLOCKS_PER_SEC); // 초 단위 변환
            cout << "time :" << time << "\t" << "sec : " << timeSecond << "초" << endl; // 시간 출력
        }
    }
    

    clock 예제

    clock()함수를 사용하면 clock()함수가 호출된 이후의 시간을 ms단위로 반환합니다. 반환값은 clock_t이며 clock_t는 clock ticks의 약자입니다. 또한 해당값을 CLOCKS_PER_SEC로 나누면 초당 clock ticks를 구할 수 있습니다.

     

    GetTickCount, GetTickCount64 함수 사용법

    #include <iostream>
    #include <windows.h> //windows.h 헤더 추가
    #pragma comment(lib, "Winmm.lib") //winmm.lib 추가
    
    using namespace std;
    void main()
    {
        for (;;) {
            unsigned long time = GetTickCount();
            DWORD time2 = GetTickCount();
            
            unsigned __int64 time_64 = GetTickCount64();
            ULONGLONG time2_64 = GetTickCount64();
            
            cout << "GetTickCount : " << time << "\t" << "GetTickCount64 : " << time2 << endl;
        }
    }
    

    GetTickCount 예제

    GetTickCount, GetTicCount64 함수는 시스템이 시작한 시점 즉 컴퓨터를 켠 시점부터 함수를 호출한 시간까지 흘러간 시간을 ms단위로 반환합니다. 위의 예제를 보시면 숫자가 일정하게 올라가지 않고 끝자리가 15~16씩 올라가는것을 보실 수 있습니다. 그 이유는 앞서 설명했던 컴퓨터에서는 시간을 측정하기 위해 타이머를 사용하는데 그 타이머의 간격이 15.6ms 이기 때문입니다.

     

    처음 GetTickCount 함수가 나왔을때의 치명적인 단점이 있었습니다. 이 함수는 윈도우가 부팅된 후 1초에 1000틱씩 카운트를 증가시키는데 카운트는 32비트값이므로 최대 49.7일간의 카운트를 유지할 수 있고 그 이상은 오버플로우가 발생하여 0으로 초기화 된다는 단점이 있었습니다. 이후 이러한 문제점을 해결한 GetTickCount64함수가 등장하게 되었습니다. GetTickCount64는 반환값이 64비트로 증가하여 오버플로우 시점이 약 5억8천년까지 기간이 늘어났기에 문제가 생길일이 없다고 보시면 됩니다.

     

    timeGetTime 함수 사용법

    #include <iostream>
    #include <windows.h> //windows.h 헤더 추가
    #pragma comment(lib, "Winmm.lib") //winmm.lib 추가
    
    using namespace std;
    void main()
    {
        for (;;) {
            unsigned long time = timeGetTime();
            DWORD time2 = timeGetTime();
            
            cout << "timeGetTime : " << time << endl;
        }
    }
    

    timeGetTime 예제

    timeGetTime() 함수는 GetTickCount와 마찬가지로 윈도우(운영체제)가 시작되어서 지금까지 흐른 시간을 1/1000 초 (milliseconds) 단위로 DWORD형을 리턴하는 함수입니다. 마찬가지로 32비트형을 리턴하므로 64일까지밖에 저장을 할수가 없습니다. 다만 getTickCount보다 좀 더 해상도가 높다는 장점이 있습니다. 위의 예제를 보시면 그래도 숫자가 1씩 증가한다는것을 보실 수 있습니다.

     

    ※ getTicCount와 timeGetTime함수를 사용하기 위해서는 windows.h 헤더 추가와 Winmm.lib를 추가하셔야 합니다.

     

    이외에도 QueryPerformanceCounter()라는 함수가 하나 더 있는데 멀티 CPU 환경에서 문제가 생긴다는 부작용도 있고 글이 너무 길어져 스킵하겠습니다. 궁금하신분은 따로 구글링 해보시길 바라겠습니다. 

     

    + ms보다 더욱 세밀한 ns단위로도 측정할 수 있는 chrono라는 함수가 C++에 추가되었습니다. 자세한 내용을 확인하시려면 아래 글을 참고해주세요.

    [C++] 나노초(ns)단위 시간 측정 chrono 함수 사용법 & 예제

     

     

    댓글

    Designed by JB FACTORY