高速でCSVファイルを読み込み2次元配列に格納する方法

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
shosinsha

高速でCSVファイルを読み込み2次元配列に格納する方法

#1

投稿記事 by shosinsha » 14年前

はじめまして、初心者で分からないところがあり質問させていただきます。
数字データが入ったCSVファイルを計算処理するために、読み込んで2次元配列に
格納するプログラムを書いたのですが、ものすごく時間が掛かって困っています。
CSVファイルは32768行、2048列、合計で67108864点もの数字が入っていて下記のように
1行読み込んで「,」で区切り数字にして格納するようなプログラムで回してみると
ファイルを読み込みだけで1時間半くらい掛かってしまいます。
CPUはi7-860でメモリ4GBあります。
もっと早く読み込める方法、良いプログラムを教えていただきたいのですが
C言語に詳しい方、何卒ご教授お願いします。

コード:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define A 2048/
#define Lnum 32768
#define B 3
#define T ','
	int N,k;
	double x[Lnum][A],o[A][B],a,b,c,d,e,f,g,h,rms[A],skw[A],kur[A];
	char st2[]=".csv";
	char st3[100];;
	char st1[100];
	char str[100];
	char str2[100];
	char str3[100];
	FILE *IN1,*IN2,*OUT;

int main(){
	printf("検定ファイル名を入力してください\n");
	printf("例(neko.csv→neko)\n");
	gets(st1);
	printf("よみこんだんよ\n");
	
	printf("輝度値ファイル名を入力してください\n");/*67108864点のCSVファイル*/
	printf("例(neko.csv→neko)\n");
	gets(st3);

	printf("よみこんだんよ\n");
	sprintf_s(str,"%s%s",st1,st2);
	IN1=fopen(str,"r");
	
	sprintf_s(str2,"%s%s",st3,st2);
	IN2=fopen(str2,"r");

char line[128], *ptr;
	int i, j;
	i=0;
	while (fgets(line, 128, IN1) != NULL) {
		ptr = line; j=0;
		do{
			//line[j]から次のタブ文字までを数値に変換
			o[i][j] = atof(ptr);
			//次のタブ文字の位置を探す
			ptr = strchr(ptr, T);
			//タブ文字の次の文字を示す
			if (ptr!=NULL) { ptr++; }
			j++;
		}while(ptr!=NULL && j<B);
		i++;
	}

/*問題の読み込み部分*/
char line1[16384], *ptr1;
	i=0;
	while (fgets(line1, 16384, IN2) != NULL) {
		ptr1 = line1; j=0;
		do{
			//line[j]から次のタブ文字までを数値に変換
			x[i][j] = atof(ptr1);
			//次のタブ文字の位置を探す
			ptr1 = strchr(ptr1, T);
			//タブ文字の次の文字を示す
			printf("x1(%d,%d)\n",i,j);
			if (ptr1!=NULL) { ptr1++; }
			j++;
		}while(ptr1!=NULL && j<A);
		i++;
	}
/*問題の読み込み部分終わり*/

//計算部分
	for(unsigned int i=0;i<A;i++){
		for(unsigned int j=0;j<Lnum;j++){
	x[j][i]=(-o[i][1]+sqrt(o[i][1]*o[i][1]-4*o[i][0]*(o[i][2]-x[j][i])))/(2*o[i][0]);
		}
	}
	a=0;
	b=0;
	c=0;
	d=0;
	e=0;
	for(unsigned int i=0;i<A;i++){
		for(unsigned int j=0;j<Lnum;j++){
			e += x[j][i];
		}
		a = e/Lnum;
		for(unsigned int j=0;j<Lnum;j++){
			b += pow(x[j][i]-a,2);
			c += pow(x[j][i]-a,3);
			d += pow(x[j][i]-a,4);
			printf("x2(%d,%d)\n",j,i);
		}
		rms[i] = sqrt(b/Lnum);
		skw[i] = c/(Lnum*pow(rms[i],3));
		kur[i] = d/(Lnum*pow(rms[i],4));
		b=0;
		c=0;
		d=0;
		a=0;
		e=0;
	}
//計算部分終わり

	sprintf_s(str,"rms_%s%s",st9,st2);//ファイル書き込み
	OUT=fopen(str,"w");
	for(unsigned int j=0;j<A;j++){
	fprintf(OUT,"%lf,%lf,%lf\n",rms[j],skw[j],kur[j]);
	}

	fclose(IN1);
	fclose(IN2);
	fclose(OUT);
	printf("終了");
	getchar();
	return 0;
}

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: 高速でCSVファイルを読み込み2次元配列に格納する方法

#2

投稿記事 by beatle » 14年前

「タブ」ではなくて「カンマ」ですね。

まあそこは置いといて、読み込みの途中でprintfをやってますね。ディスプレイへの出力はたいてい遅いので、もしかしたらそこがボトルネックになっているかもしれません。

コード:

            //タブ文字の次の文字を示す
            printf("x1(%d,%d)\n",i,j);
を実行しないようにしたらどうでしょうか。

naohiro19
記事: 256
登録日時: 15年前
住所: 愛知県

Re: 高速でCSVファイルを読み込み2次元配列に格納する方法

#3

投稿記事 by naohiro19 » 14年前

コード:

gets(st1);
ではなく

コード:

fgets(st1, 100, stdin);
を使いましょう。

shosinsha

Re: 高速でCSVファイルを読み込み2次元配列に格納する方法

#4

投稿記事 by shosinsha » 14年前

beatleさんありがとうございます。
printfを消したら一瞬で処理が終わりました。
ディスプレイへの出力がこんなに重いものだとは思いませんでした。

閉鎖

“C言語何でも質問掲示板” へ戻る