アプリ版:「スタンプのみでお礼する」機能のリリースについて

いつも利用させてもらって助かっています。

あるプログラムを作成しているのですが、ファイル入力の部分がネックとなってしまって、全体が使いものにならない状況に陥っています。
たくさんのデータをfread1回で読み込むことにより、読み込み速度はずいぶんと改善されましたが、まだ圧倒的に遅い状況です。システムコールを使いましたが、ほとんど改善されませんでした。
読み込み/書き込みの速度を改善する方法として,SSDメモリを使ったりする方法があると思いますが,プログラムの観点から改善できるところはないでしょうか?
下に、ファイル読み込みの部分だけ記述したコードを添付させて頂いたので、改善できる点があれば、御指摘頂けると助かります。

なお、前提として,
(1)データはスタック領域だと不足するので、ヒープ領域に確保
(2)データファイルは改行無しの一連のデータ
とします。

ちなみに、環境は
OS   : CentOS5.3
memory   : 6GB
コンパイラ : gcc
です。

よろしくお願いします。

//-----------------------------------------------------
//通常バージョン
#include <stdio.h>
#include <stdlib.h>

#define SIZE (512*1024*1024) //500MB

int main(void)
{
unsigned long int i;
unsigned char *data;
FILE *fp;

data = (unsigned char *)malloc(SIZE);
if(data == NULL) {
printf("メモリが確保できません\n");
exit(EXIT_FAILURE);
}

fp = fopen("filein.dat", "rb");
fread( data, sizeof( unsigned char), (int)SIZE, fp );
fclose(fp);

/*
//表示
for( i=0; i<SIZE; i++ ){
printf("%2x", data[i]);
}
puts("");
*/

fp = fopen("fileout.dat", "w");
fwrite( data, sizeof( unsigned char), (int)SIZE, fp);
fclose(fp);

free(data);
return 0;
}

//-----------------------------------------------------
//readシステムコールを使ったバージョン
#include <stdio.h>
#include <stdlib.h>

#define SIZE (512*1024*1024) //500MB

int main(void)
{
unsigned long int i;
unsigned char *data;

data = (unsigned char *)malloc(SIZE);
if(data == NULL) {
printf("メモリが確保できません\n");
exit(EXIT_FAILURE);
}

int fd;
fd = open( "filein.dat" );
read( fd, data, sizeof(unsigned char)*SIZE);
close(fd);

/*
//表示
for( i=0; i<SIZE; i++ ){
printf("%2x", data[i]);
}
puts("");
*/

FILE *fp;
fp = fopen("fileout.dat", "w");
fwrite( data, sizeof( unsigned char), (int)SIZE, fp);
fclose(fp);

free(data);
return 0;
}

A 回答 (6件)

>「まだ圧倒的に遅い状況」と申し上げましたのは、


>全体の処理に対してファイルの読み書きが占める割合が
>50%以上を占めてしまっている、ということです。

ディスク入出力処理に時間がかかるコト、そんなにおかしいですかね。
入出力に時間がかかるのは、常識だと思うのですが。
入出力性能要件を全体処理に対する割合で算出することがナンセンスに思えます。

確認なんですが、質問タイトルは「読み書きを早くしたい」、
本文は「ファイル入力の部分がネックとなってしまって」
とありますが、問題視されているのは、読み込みですか?
>500MB / 0.256s = 1953MB/s ≒ 1.9GB/s

500MBを0.256秒で読み込めているのが異常に速くて、にわかには信じがたいです。
OSがファイルをキャッシュして、メモリ上に蓄えてるんじゃないですか?

>ちなみに、RAMディスク
キャッシュ vs RAMディスクだとすると、どちらも同じRAM上なので、
速度は同程度になるような気がします。
PCを再起動して1回目の計測だと10秒ぐらいかかったりしませんか?

読み込み速度の基準は、デバイスのベンチマークテストなどを行って、
それを基準にしたほうがいいと思います。
    • good
    • 0

んで結局入力情報をどうしたいのでしょう?


サンプルを見た限りでは特に問題点はなさそうですね。
ロジック的に効率の悪い処理をしていませんかね。

ファイルIO関係で遅くなるケースの良くあるパターンは
1. バッファリングなしで少しずつ読み書きしている
2. ファイルのオープンクローズ回数が多い
3. ロック待ち

それぞれの解決方法は
1.は read/write を fread/fwrite に変更して setvbuf にて大きなバッファリング領域を確保してあげる
変更後はフラッシュのタイミングに注意が必要です。dsyncとかね
2.はロジックの見直しもありますし、オープンしたファイルハンドルをキャッシュするなんていう手もあります
プロセスごとオープンできるファイル数には限界があるので超えないようにする必要があります
特にファイルのクローズはコストが大きいです。
3.はどうしようもないですね。

おそい、おそい、いうだけじゃなんの解決もできませんよ。
物量的な統計情報をださないと、おそいのがどのくらい遅いのかわからないです。

たとえば、30分以内に終わるべきものが2時間かかってしまうとか
#まぁここまでくるとさすがにIOじゃなくでアルゴリズムが悪いのでしょうけど。
    • good
    • 0

mmap (ないし MapViewOfFile) というのは既に提案してるんだけどね>#4.


あるいは, バッファリングを禁止してから fread なり read でいいのかもしれない.

参考URL:http://oshiete1.goo.ne.jp/qa5563519.html
    • good
    • 1

Linuxを使っているのなら、mmap()でファイルをメモリ空間に割り当ててしまうのがいいのでは?

    • good
    • 0

>まだ圧倒的に遅い状況


抽象的な表現ですな。
ハードの限界点を見極めてからソフトがそれに近づくというのが基本ではないですかな。
今、貴方のソフトはハードの力を何%ぐらい引き出せているのでしょう。
100%近く引き出しているなら、ソフトの力でそれを引き上げるのは無理です。

http://www.cc.u-tokyo.ac.jp/publication/news/VOL …

この回答への補足

「まだ圧倒的に遅い状況」と申し上げましたのは、
全体の処理に対してファイルの読み書きが占める割合が50%以上を占めてしまっている、ということです。

ちなみにファイル読み書きの部分のみ取り出して実行時間を調べてみたら約500MBのデータに対し、0.256sで、
I/Oスピードは
500MB / 0.256s = 1953MB/s ≒ 1.9GB/s
でした。

ちなみに、RAMディスク
http://itpro.nikkeibp.co.jp/article/Keyword/2007 …
を使ってメモリ領域にファイルを置いてアクセスしてみても上記のI/Oスピードとほとんど変わりませんでした(こうなった理由がさっぱりわかりません)。


ちなみに、紹介して頂いたページのpdfも参考にして、
setvbuf(fp,NULL,_IOFBF, 512*1024*1024);
のようにバッファサイズを変えてみたりしたのですが、まったく変わりませんでした。

補足日時:2010/01/04 14:12
    • good
    • 0

WindowsAPIを使用しても良い状態であるならば、「ファイル・マッピング」機能が使えると思います。


日経ソフトウェア2010年1月号に記載されています。
    • good
    • 0
この回答へのお礼

回答有難う御座います。
説明足らずで申し訳ありません。
OSはcentOS5.3(Linux)を使っているので,WindowsAPIを使用できない状況にありますが、参考になりました。

どうも有難う御座いました。

お礼日時:2010/01/04 14:17

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A