ページ 11

getrusageを用いた実行時間計測の方法

Posted: 2008年7月29日(火) 15:17
by ビスタ
こんにちは。さっそくですが質問です。タイトルの通りなのですが…
C言語で特定の処理の実行時間を計るプログラムを使いたいです。
基本的な部分は把握したつもりですが、どうも組み込もうと思うと
コンパイルがエラーを吐いてしまいます。

学校の課題で、クイックソートとバブルソートの実行時間比較をする。
というのがあって、ソート部分のプログラムと計算結果を表示するプログラム
をメインのプログラム(=整数乱数配列を生成するプログラム)に外部呼出し
しています。

つまり

メインの乱数生成プログラム、ソートプログラム、表示プログラム

の3つのソースがある状態で、ソートの並び替え部分の実行時間を測定したい
んです。測定結果をソートプログラムのほうで表示するようにすると

printf関数が定義されていないとのエラーがでます。#include<stdio.h>を
ソートプログラムに追加するとよくわからないエラーが出てしまい、どうした
らいいのか分からない状態です。


環境

OS:Win vista 32bit
コンパイラ:gcc (cygwinを利用)

↓問題のある quickSort.c
#include<time.h>

#include<sys/time.h>

#include<sys/resource.h>

#include<stdio.h>



double getrusage_sec(){
	
	struct rusage t;
	
	struct timeval tv;
	
	getrusage(RUSAGE_SELF, &t);
	
	tv=t.ru_utime;
	
	return tv.tv_sec+(double)tv.tv_usec*1e-6;
	
}



void quickSort(int data[/url], int start, int end)
{
	
	double t1,t2;	
	
	int i,j, p, t;

	
	p = data[(start+end)/2];
 
	
	i = start;
	
	j = end;
	
	
	t1=getrusage_sec();

	

	while (1) {    
	  
		while (data<p) {
	    
			i++;
	
		}
	  
		while (p<data[j]) {
	    
			j--;
	
		}

	

		if (i>=j) {	
	  
			break;
	
		}

	
		t = data;
	

	data = data[j];

	
		data[j] = t;

	
		i++;
	
		j--;
	

}

	

	if (start < i-1) {
		quickSort(data,start,i-1);
	
	}

	

	if (j+1 < end) {
	  
		quickSort(data,j+1,end);

	}



	t2=getusage_sec();

	fprintf(stdout,"use_time=%10.70f\n",t2-t1);
 
	return ;

}


他に必要なソースとかあったら教えてください。追記します

Re:getrusageを用いた実行時間計測の方法

Posted: 2008年7月29日(火) 16:20
by Mist
> よくわからないエラー
コンパイルエラーであればエラーメッセージを全て載せられた方が良いかと思います。

Re:getrusageを用いた実行時間計測の方法

Posted: 2008年7月29日(火) 17:55
by たいちう
> の3つのソースがある状態で、ソートの並び替え部分の実行時間を測定したい
> んです。測定結果をソートプログラムのほうで表示するようにすると

測定結果はソートプログラムの呼び出し元(例えばmain関数)で表示した方がスマートだと思うし、
もしかしてそれだけで解決しませんか?

Re:getrusageを用いた実行時間計測の方法

Posted: 2008年7月29日(火) 18:53
by ビスタ
>Mistさん
そうですね。でももう一度見直したらスペルミス発見して、直したら
エラー吐かなくなりました。ご指摘ありがとうございます。

>たいちうさん
その方法だとソートプログラムがデータを読み込むとき…えーとなんて
言えばいいのか忘れてしまいました(汗
うーん。とりあえず、main関数で表示させるようにしてみたのですが…
小数点以下70桁でも時間の表示が「0」しか出ませんでした。

発生させる乱数の数は1000で試したのですが、クイックソートだとまだ
乱数の数が少ないのでしょうか…。それとも他に原因があるのでしょう
か。今のところ発生させる乱数の数が少ないか、表示桁数が足りないか
のどちらかしか思い浮かばないのですが。

指摘があるとありがたいです。お願いします。

Re:getrusageを用いた実行時間計測の方法

Posted: 2008年7月29日(火) 19:21
by たいちう
他の原因でしょう、多分。
乱数の数を10000や100000にしたりしても同じ結果ならば、間違いなく。

原因の心当たりは、時刻のデータを十分な精度で取れていないとか、
変数の受け渡しに失敗しているとか、というところかと。

GetTickCount()を使って書くとすると、こんな感じ。
int main() {
	時刻1 = GetTickCount();
	quickSort();
	時刻2 = GetTickCount();
	(時刻2 - 時刻1)を表示;
}

Re:getrusageを用いた実行時間計測の方法

Posted: 2008年7月29日(火) 20:38
by ビスタ
>たいちうさん
うーん。↓と似たようなものだと思ってるんですが。

#include<stdlib.h>
#include<time.h>
#include<sys/time.h>
#include<sys/resource.h>
#include<stdio.h>

double getrusage_sec(){
	struct rusage t;
	struct timeval tv;
	getrusage(RUSAGE_SELF, &t);
	tv=t.ru_utime;
	return tv.tv_sec+(double)tv.tv_usec*1e-6;
	}

extern void quickSort(int data[/url],int start,int end);
extern void show_array(int data[/url],int size);

int main(void){
  
	double t1,t2;
	int data[100],i;

	time_t now;
	srand((unsigned int)time(&now));

	for(i=0;i<100;i++){
		data=1+(int)(100.0*rand()/RAND_MAX);
	}

	show_array(data,100);

	fprintf(stdout,"\n\n---After sort---\n\n\n");

	t1=getrusage_sec();
	quickSort(data,0,99);
	t2=getrusage_sec();

	fprintf(stdout,"utime=%10.70f\n",t2-t1);
	show_array(data,100);

	return 0;
}



違うんですかね。1万も10万も結果一緒(計測結果が0秒)になるので
何かおかしいはずなんですけど…。他の時間計測方法に変えたほうが
いいのでしょうか。

http://kzk9.net/column/time.html

ここのを参考にしてます。

Re:getrusageを用いた実行時間計測の方法

Posted: 2008年7月29日(火) 20:49
by たいちう
> うーん。↓と似たようなものだと思ってるんですが。

似てますね。t1とt2を直接表示するとどうなります?
getrusage_sec()の中で途中経過を表示すると?

それとdoubleの精度は70桁もないので、桁数を増やすのは無意味ですよ。

Re:getrusageを用いた実行時間計測の方法

Posted: 2008年7月29日(火) 21:34
by ビスタ
直接表示…というと
#include<time.h>
#include<sys/time.h>
#include<sys/resource.h>
#include<stdio.h>

double getrusage_sec(){
	struct rusage t;
	struct timeval tv;
	getrusage(RUSAGE_SELF, &t);
	tv=t.ru_utime;
	return tv.tv_sec+(double)tv.tv_usec*1e-6;
	}

int main(void){
  
	double t1,t2;

	t1=getrusage_sec();
	t2=getrusage_sec();

	fprintf(stdout,"utime=%10.70f\n",t2-t1);

	return 0;
}
こういうことですか?
0しか出ませんね…。根本的にどこか間違ってる…のでしょうか。
ちょっと探してみます。

Re:getrusageを用いた実行時間計測の方法

Posted: 2008年7月29日(火) 21:40
by たいちう
> こういうことですか?

違います。
t1を表示してください。次にt2を表示してください。
引き算の答えが期待と違っているのだから、
引く数と引かれる数はどうなっていますか?と。

Re:getrusageを用いた実行時間計測の方法

Posted: 2008年7月29日(火) 22:18
by ビスタ
>t1を表示してください。次にt2を表示してください。

あ、そういうことですか。t1とt2の間にquickSortを挟んで試してみましたが
t1もt2も「0」の羅列でした。どうもうまく時間の取得ができてないですね…。

Re:getrusageを用いた実行時間計測の方法

Posted: 2008年7月30日(水) 09:22
by たいちう
> どうもうまく時間の取得ができてないですね…。
↑この場合のための、↓このコメントです。
> getrusage_sec()の中で途中経過を表示すると?


経過時間取得の失敗(質問時の状態)

現在時刻取得(getrusage_sec)の失敗(今分かっていること)

getrusageの失敗(これはまだ憶測、確認すること!)

と、だんだん絞り込み、キーワード「getrusage」でググったりすると解決するかも。
手に届くところにgccの環境がないので私には試せません。
解決できない場合は、他の方のレスを待って下さい。

もしも数日レスがつかない場合は、解決してないことが目立つように
改めて「getrusageの失敗」とかいうタイトルで新しい質問をするのもありかと思います。

Re:getrusageを用いた実行時間計測の方法

Posted: 2008年7月30日(水) 22:08
by ビスタ
原因はgetrusageではなく、メインのプログラムに書いた
quickSortの呼出しでした。
quickSort(data,0,99);
になっていますが…quickSortのプログラムを見直したところ
変数に格納する値が間違ってました。quickSortのアルゴリズ
ム自体を誤認識していたんだと思ってます。

並べ替えるときの基準を置くときに、「中間に該当する【数値】」
を基準にしているのだと考えてしまっていたためのミスだったようです。
「存在する要素数全体の折り返し地点」を基準にしなければならないので

quickSort(data,0,要素数-1);

と書き直せば10000程度以上の配列を利用した場合に時間計測できました。
(1000くらいだと早すぎて0しか出力されない)

回答、ありがとうございました。