C言語で実時間を測定する Windows && Linux

c言語で処理の 実時間 測定をするTipsを総合してパーフェクトな時間測定を出来るようにした。

自分の場合はTimeWatcher構造体を作成して時間を測定している。

ヘッダファイル

#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#define MS_MODE
#endif

#ifdef MS_MODE
#include <windows.h>
#include <mmsystem.h>
#pragma comment( lib, "winmm.lib" )
#else
#include <sys/time.h>
#endif

// =================
// measure time(sec)
// =================

typedef struct TimeWatcher
{
#ifdef MS_MODE
    DWORD start;
    DWORD end;
#else
    double start;
    double end;
#endif
} TimeWatcher;
void start(TimeWatcher* tw);
void end(TimeWatcher* tw);
void print_time_sec(TimeWatcher* tw);

ソースファイル

// =================
// measure time(sec)
// =================

#ifndef MS_MODE
double gettimeofday_sec()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec + tv.tv_usec * 1e-6;
}
#endif

void start(TimeWatcher* tw)
{
#ifdef MS_MODE
    tw->start = timeGetTime();
#else
    tw->start = gettimeofday_sec();
#endif
}

void end(TimeWatcher* tw)
{
#ifdef MS_MODE
    tw->end = timeGetTime();
#else
    tw->end = gettimeofday_sec();
#endif
}

void print_time_sec(TimeWatcher* tw)
{
#ifdef MS_MODE
    printf("%10.10f(sec)\n", (double)(tw->end - tw->start) / 1000.0);
#else
    printf("%10.10f(sec)\n", tw->end - tw->start);
#endif
}

clock()を使用する時間測定の問題点

#include <time.h>

typedef struct TimeWatcher
{
      clock_t start;
      clock_t end;
} TimeWatcher;

void start(TimeWatcher* tw)
{
      tw->start = clock();
}

void end(TimeWatcher* tw)
{
      tw->end = clock();
}

void print_time_sec(TimeWatcher* tw)
{
      printf("Time : %f(sec)\n", (double)(tw->end-tw->start)/CLOCKS_PER_SEC);
}

clock()

iプログラム実行開始からの経過時間(プロセッサ時間)を返却します。経過時間の精度は処理系に依存します。
clock関数を2回呼び出し、経過時間の差を求めることにより、処理時間を算出することが出来ます。
経過時間を秒で表現するには、CLOCKS_PER_SECで割る必要があります。

clock

上記の通り、clock_tはプロセッサ時間を測定するので実時間とは必ずしも一致しない。

しかも、マルチコア処理の時間測定を行う場合にclock()を使用すると、それどれのコアでの計算時間を合計したものが測定されてしまう。

つまり、実時間を測定したい場合はclock()の使用はできないということ。

解決策

正確な実行時間を測定するのに有用なツールが環境によって異なるが存在している。

  • Unix系環境ではsys/time.h
  • VC++環境ではtimeGetTime()

それぞれ、sys/time.hはマイクロ秒、timeGetTime()はミリ秒の精度がある。

Unix系環境

ヘッダファイル

#ifndef UTIL_H_INCLUDE
#define UTIL_H_INCLUDE

// =================
// measure time(sec)
// =================

typedef struct TimeWatcher
{
        double start;
        double end;
} TimeWatcher;

void start(TimeWatcher* tw);
void end(TimeWatcher* tw);
void print_time_sec(TimeWatcher* tw);

#endif // #ifndef UTIL_H_INCLUDE

ソースファイル

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

// =================
// measure time(sec)
// =================

double gettimeofday_sec()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec + tv.tv_usec * 1e-6;
}

void start(TimeWatcher* tw)
{
      tw->start = gettimeofday_sec();
}

void end(TimeWatcher* tw)
{
     tw->end = gettimeofday_sec();
}

void print_time_sec(TimeWatcher* tw)
{
     printf("%10.10f(sec)\n", tw->end - tw->start);
}

VC++環境

ヘッダファイル

#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#include <windows.h>
#include <mmsystem.h>
#pragma comment( lib, "winmm.lib" )

typedef struct TimeWatcher
{
    DWORD start;
    DWORD end;
} TimeWatcher;
void start(TimeWatcher* tw);
void end(TimeWatcher* tw);
void print_time_sec(TimeWatcher* tw);
#endif

ソースファイル

// =================
// measure time(sec)
// =================

#if defined(_MSC_VER) && (_MSC_VER >= 1020)

void start(TimeWatcher* tw)
{
    tw->start = timeGetTime();
}

void end(TimeWatcher* tw)
{
    tw->end = timeGetTime();
}

void print_time_sec(TimeWatcher* tw)
{
    printf("%10.10f(sec)\n", (double)(tw->end - tw->start) / 1000.0);
}

#endif