C言語でclock関数を使っても0にしかならないのはナゼ?

C言語でミリ秒単位までの時間計測にclock関数を使っている方は多いかと思います。

組んだプログラムの処理速度を計測するためにclock関数を使っている方も多いでしょう。

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

int main() {
	clock_t start,end,diff;

	start = clock();

	//何らかの処理

	end = clock();
	diff = end - start;
	
	//clock_t型の正体ははlong型なので、%dではなく%loが正解
	printf("処理時間は%loミリ秒です",diff);

	return 0;
}

clock関数を用いて処理時間を計測するのはこの方法で間違っていないのですが、間違っていないにもかかわらずend - startの計算結果が0になってしまうことがあります。

今回は、clock関数を使って正しく処理速度の計測をしているにも関わらず、処理時間が0ミリ秒になってしまう原因と対処方法を解説します。

目次から探す

clock関数で処理時間を計測すると0になる理由

理由は一つ。

処理時間を計測する処理の処理時間が1ミリ秒未満だからです。1ミリ秒以下は切り捨てられるので、clock関数を使って処理時間を計算しても0にしかならないのです。

そのため、もっと時間がかかる負荷の大きい処理をしてあげると1ミリ秒以上の結果になるはずです。

以下の1,000万回メモリの確保をしながら値の交換を行うプログラムを実行すれば、さすがに1ミリ秒以上の結果が表示されるはずです。

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

int main() {
	clock_t start,end,diff;

	start = clock();

	for (int i = 0; i < 10000000; i++) {
		int a,b,c;
		a=1;
		b=2;
		c=a;
		a=b;
		b=c;
	}

	end = clock();
	diff = end - start;
	
	printf("処理時間は%loミリ秒です",diff);

	return 0;
}

clock関数を使って計算した処理時間が0になる場合は、その処理が1ミリ秒もかからずに完了しているということを覚えておいてください。

1ミリ秒未満の処理時間を計測する場合は?

1ミリ秒未満なら何マイクロ秒・ナノ秒なのか気になる方もいますよね。

C言語には1ナノ秒単位(0.000001ミリ秒単位)で時間計算する方法があります。ナノ秒単位であればかなり小規模な処理でも計測できるでしょう。

ナノ秒単位で計測したい場合はclock関数ではなくtimespec_get関数を使います。

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

int main() {

	struct timespec start,end;
	timespec_get(&start, TIME_UTC);

	int a,b,c;
	a=1;
	b=2;
	c=a;
	a=b;
	b=c;

	timespec_get(&end, TIME_UTC);
	long diff = end.tv_nsec - start.tv_nsec;
	
	printf("処理時間は%loナノ秒です",diff);

	return 0;
}

こちらはループ処理もしていないただただ値を1回だけ交換する処理を計測したものですが、ナノ秒単位であれば処理速度が返ってきます。

この方法を使っても0が返ってくる場合は、正真正銘0ナノ秒未満しかかかっていない処理ということですが、timespec_get関数の処理時間もごく僅かに含まれるので、0にはなることはまずありません。

sleep関数との関係に注意

注意点として、clock関数で処理時間を計測する際に、sleep関数は挟まないようにしましょう。

clock関数はプログラムが実行されてからの経過時間を取得する関数なのですが、sleep関数を使って停止している時間はカウントされないのです。

例えば以下のコードの9行目func1();の処理時間が500ミリ秒だった場合、1500ミリ秒(1.5秒)ではなく500ミリ秒が出力されます。

#include<stdio.h>
#include<time.h>
#include <unistd.h>

int main() {
	clock_t start,end,diff;

	start = clock();
	sleep(1); //1秒停止
	func1();
	end = clock();
	diff = end - start;
	
	//clock_t型の正体ははlong型なので、%dではなく%loが正解
	printf("処理時間は%loミリ秒です",diff);

	return 0;
}

sleep関数を使うとプログラムそのものの動作が一時的に止まってclock関数の計測対象である実行時間にカウントされないので注意しましょう。

正確性を求めるならtimespec_get関数を使う

処理時間の計測にはclock関数が有名ですが、1ミリ秒未満も正確に計算するならtimespec_get関数がおすすめです。

書き方もほとんど同じであり、ナノ秒からミリ秒への変換も簡単なので、覚えておくと時間計測の際に役立つでしょう。

目次から探す