clock

clock

코드가 실제로 얼마나 CPU를 썼는지 재보고 싶을 때, 특히 "벽시계(wall clock)와 얼마나 다른가"를 확인하고 싶을 때 쓰는 함수가 clock()이에요. <time.h>에 정의돼 있어요.

출처: cppreference

본문

clock()은 프로그램 실행과 관련된 구현 정의 시대(era) 이후로 프로세스가 사용한 대략적인 프로세서 시간을 돌려줘요.

  • 돌려준 값을 초로 바꾸려면 CLOCKS_PER_SEC로 나눠요.
  • clock 시대의 시작점이 프로그램의 시작과 반드시 일치하지는 않아서, 서로 다른 두 호출이 돌려준 값의 차이만이 의미를 가져요.
clock_t clock(void);

clock 시간은 운영체제가 프로그램에 준 실행 자원에 따라 벽시계보다 빠르게도 느리게도 흘러요.

  • CPU를 다른 프로세스와 공유하면 벽시계보다 느리게 진행될 수 있어요.
  • 반대로 현재 프로세스가 멀티스레드이고 실행 코어가 여러 개라면 벽시계보다 빠르게 진행될 수 있어요.

반환값

프로그램이 지금까지 사용한 프로세서 시간을 돌려줘요.

  • 프로세서 시간을 구할 수 없으면 (clock_t)(-1)을 돌려줘요.
  • 프로세서 시간의 값이 clock_t로 표현할 수 없으면 정해지지 않은 값을 돌려줘요.

주의

  • POSIX 호환 시스템에서는 clock id가 CLOCK_PROCESS_CPUTIME_IDclock_gettime이 더 좋은 해상도를 제공해요.
  • 일부 구현에서는 clock()의 값이 감싸질(wrap) 수 있어요. 예를 들어 clock_t가 부호 있는 32비트 정수이고 CLOCKS_PER_SEC1000000이면, 약 2147초(약 36분) 뒤에 값이 감싸요.

예시

아래 예시는 clock()으로 잰 CPU 시간과 clock_gettime()으로 잰 CPU·벽시계 시간을 비교해요. 두 스레드가 일을 나눠 하므로 CPU 시간이 벽시계보다 크게 나오는 걸 볼 수 있어요.

#ifdef __STDC_NO_THREADS__
    #define _POSIX_C_SOURCE 199309L
    #include <pthread.h>
#else
    #include <threads.h>
#endif
#include <stdio.h>
#include <time.h>

int f(void* thr_data) // POSIX에서는 void*
{
    (void) thr_data;
    volatile double d = 0;
    for (int n = 0; n < 10000; ++n)
       for (int m = 0; m < 10000; ++m)
           d += d * n * m;
    return 0;
}

int main(void)
{
    struct timespec ts1, tw1;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts1);
    clock_gettime(CLOCK_MONOTONIC, &tw1);
    clock_t t1 = clock();

#ifndef __STDC_NO_THREADS__
    thrd_t thr1, thr2;
    thrd_create(&thr1, f, NULL);
    thrd_create(&thr2, f, NULL);
    thrd_join(thr1, NULL);
    thrd_join(thr2, NULL);
#endif

    struct timespec ts2, tw2;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts2);
    clock_gettime(CLOCK_MONOTONIC, &tw2);
    clock_t t2 = clock();

    double dur = 1000.0 * (t2 - t1) / CLOCKS_PER_SEC;
    double posix_dur = 1000.0 * ts2.tv_sec + 1e-6 * ts2.tv_nsec
                           - (1000.0 * ts1.tv_sec + 1e-6 * ts1.tv_nsec);
    double posix_wall = 1000.0 * tw2.tv_sec + 1e-6 * tw2.tv_nsec
                            - (1000.0 * tw1.tv_sec + 1e-6 * tw1.tv_nsec);

    printf("CPU time used (per clock()): %.2f ms\n", dur);
    printf("CPU time used (per clock_gettime()): %.2f ms\n", posix_dur);
    printf("Wall time passed: %.2f ms\n", posix_wall);
}

가능한 출력(예시):

CPU time used (per clock()): 1580.00 ms
CPU time used (per clock_gettime()): 1582.76 ms
Wall time passed: 792.13 ms

더 알아보기

  • 시스템의 현재 달력 시간(epoch 이후)을 얻는 함수는 time()을 봐요.
  • cppreference의 clock 원문을 참고해요.