見出し画像

高精度(高解像度)な時刻の取得 (Linux, x64, C言語) 1

Linux と x64 CPU で,細かい(解像度が高い)時刻調査方法を説明します.

clock_gettime()

説明

解像度(resolution)は 1ns(ナノ秒, 10^-9秒) です.

使用方法

#include <stdio.h>
#include <time.h>
void main(){
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        printf("%ld.%09ld\n",ts.tv_sec,ts.tv_nsec);
}

使用例 と 実行例

#include <stdio.h>
#include <time.h>
#include <unistd.h>
void main(){
        struct timespec ts0, ts1;
        clock_gettime(CLOCK_REALTIME, &ts0);
        sleep(2);
        clock_gettime(CLOCK_REALTIME, &ts1);
        printf("%ld.%09ld\n",ts0.tv_sec,ts0.tv_nsec);
        printf("%ld.%09ld\n",ts1.tv_sec,ts1.tv_nsec);
}

実行結果

978274800.001801282
978274802.002857942

CLOCK_REALTIME以外でclock_gettime()

clock_gettime()は第1引数に clockid を指定します.
clockidとしては,以下のものを指定できます.
それぞれ解像度が異なります.

CLOCK_REALTIME
CLOCK_REALTIME_ALARM (since Linux 3.0; Linux-specific)
CLOCK_REALTIME_COARSE (since Linux 2.6.32; Linux-specific)
CLOCK_TAI (since Linux 3.10; Linux-specific)
CLOCK_MONOTONIC
CLOCK_MONOTONIC_COARSE (since Linux 2.6.32; Linux-specific)
CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific)
CLOCK_BOOTTIME (since Linux 2.6.39; Linux-specific)
CLOCK_BOOTTIME_ALARM (since Linux 3.0; Linux-specific)
CLOCK_PROCESS_CPUTIME_ID (since Linux 2.6.12)
CLOCK_THREAD_CPUTIME_ID (since Linux 2.6.12)

clock_getres man page

各clockidのresolution

解像度の調査方法

#include <stdio.h>
#include <time.h>
int clockid[11]={ CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_REALTIME_COARSE, CLOCK_TAI, CLOCK_MONOTONIC, CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_RAW, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID};
char clockidname[11][25]={"CLOCK_REALTIME", "CLOCK_REALTIME_ALARM", "CLOCK_REALTIME_COARSE", "CLOCK_TAI", "CLOCK_MONOTONIC", "CLOCK_MONOTONIC_COARSE", "CLOCK_MONOTONIC_RAW", "CLOCK_BOOTTIME", "CLOCK_BOOTTIME_ALARM", "CLOCK_PROCESS_CPUTIME_ID", "CLOCK_THREAD_CPUTIME_ID"};
void main(){
        struct timespec res;
        int i;
        for(i=0; i<11; i++){
                if( ! clock_getres(clockid[i], &res) ){
                        printf("%s %ld%09ld ns\n", clockidname[i], res.tv_sec, res.tv_nsec);
                }
        }

}

調査結果

CLOCK_REALTIME 0000000001 ns
CLOCK_REALTIME_ALARM 0000000001 ns
CLOCK_REALTIME_COARSE 0004000000 ns
CLOCK_TAI 0000000001 ns
CLOCK_MONOTONIC 0000000001 ns
CLOCK_MONOTONIC_COARSE 0004000000 ns
CLOCK_MONOTONIC_RAW 0000000001 ns
CLOCK_BOOTTIME 0000000001 ns
CLOCK_BOOTTIME_ALARM 0000000001 ns
CLOCK_PROCESS_CPUTIME_ID 0000000001 ns
CLOCK_THREAD_CPUTIME_ID 0000000001 ns

CLOCK_REALTIMEは 1 ns.CLOCK_REALTIME_COARSEは 4000000 ns

rdtsc命令

説明

解像度は 1 CPUクロックです.

使用方法

#define RDTSC(X) asm volatile ("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" : "=a" (X) :: "%rdx")

https://www.cc.u-tokyo.ac.jp/public/VOL10/No5/200809tuning.pdf

により取得可能です.

#include <stdio.h>
#define RDTSC(X) asm volatile ("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" : "=a" (X) :: "%rdx")
void main(){
        long long int tsc;
        RDTSC(tsc);
        printf("%lld\n", tsc);
}

使用例 と 実行例

#include <stdio.h>
#include <unistd.h>
#define RDTSC(X) asm volatile ("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" : "=a" (X) :: "%rdx")
void main(){
        long long int tsc0, tsc1;
        RDTSC(tsc0);
        sleep(2);
        RDTSC(tsc1);
        printf("%lld %lld %lld\n", tsc0, tsc1, tsc1-tsc0);
}

実行結果

25129402361054 25136202666144 6800305090

gettimeofday()

説明

解像度は 1us(マイクロ秒, 10^-6秒) です.

使用方法

#include <stdio.h>
#include <sys/time.h>
void main(){
        struct timeval tv;
        gettimeofday( &tv, NULL);
        printf("%ld.%06ld\n",tv.tv_sec, tv.tv_usec);
}

使用列 と 実行例

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
void main(){
        struct timeval tv0, tv1;
        gettimeofday( &tv0, NULL);
        sleep(2);
        gettimeofday( &tv1, NULL);
        printf("%ld.%06l\n",tv0.tv_sec, tv0.tv_usec);
        printf("%ld.%06l\n",tv1.tv_sec, tv1.tv_usec);
}

実行結果

978274867.886919
978274869.887422

コメント

gettimeofday() を使うのは辞めましょう。

POSIX.1-2008 marks gettimeofday() as obsolete, recommending the use of clock_gettime(2) instead.

https://man7.org/linux/man-pages/man2/gettimeofday.2.html

gettimeofday() は廃止対象です.代わりにclock_gettime()を使いましょう.

とのことです。

この記事が気に入ったらサポートをしてみませんか?