- PR -

カンマ区切りの行の高速読み込みでプログレスバーを出す。(C++)

投稿者投稿内容
さくら
常連さん
会議室デビュー日: 2004/06/15
投稿数: 31
投稿日時: 2005-11-22 18:24
大きいサイズのファイルを開いてカンマ区切りの行を読み込んで解析したいのですが、ファイルのサイズが大きいため時間がかかってしまいます。
そこで、プログレスバーを出すことにしました。
ftell(fp) / (double)filesize * 100
で、プログレスバーの値をとることにしましたが、ftellは2Gまでしかサポートしていません。
他にファイルの現在位置を取得する方法はないでしょうか?
また、この方法以上に高速に読む方法はありますか?
今は、
while(fscanf(fp,"%d %d\n",&t,&t1) != EOF)
という方法で一行取得しながら読み込んでいます。

アドバイスよろしくお願いいたします。
sia
常連さん
会議室デビュー日: 2004/05/02
投稿数: 38
投稿日時: 2005-11-22 19:08
こんばんわ。

2GB超のファイルポインタの位置を取得するためには、
Windowsネイティブの関数である、
CreateFile、
ReadFile、
SetFilePointerEx
などを使用しなければならないです。

上記を使用してファイルポインタの位置をとるには、
SetFilePointerEx(hFile、0,&newPos, FILE_CURRENT);
でnewPosに取得できます。

ただこれらの関数群を使うと、文字列の一行単位での読み込みが
激しく面倒になります。

高速化についてですが、シーケンシャルなアクセスのようなので、CreateFileの引数にFILE_FLAG_SEQUENTIAL_SCAN
を指定してやると高速に動作する可能性はあります。
#期待はそれほどもてませんが。
未記入
大ベテラン
会議室デビュー日: 2005/03/12
投稿数: 148
投稿日時: 2005-11-22 21:40
実際速くなるかはやってみないとわからないから、どうだか判らん。
俺は優しくない(ある意味やさしい)ので、速くなるか確認しません。

1MBとか一気にメモリ上に読み取るとか。
fscanfで一寸ずつ読むより速いかもしれない。
原因がファイルをちまちま読み込むことだったらね。
そうでなかったら無駄骨になるってことかも。

ただ、1MBのところがちょうど改行の位置になるとは限らない。
その辺の処理が面倒で、どれくらい速くなるかも不明ときたもんだ。

while(fscanf(fp,"%d %d\n",&t,&t1) != EOF)
を使わず自分で数字を読み込む処理を書くとか。
sscanfより速いコードを書けるなら速くなるでしょう。
速くならなかったらatoiやsscanfを使うとか。
myama
会議室デビュー日: 2005/11/11
投稿数: 5
投稿日時: 2005-11-23 10:46
未記入さんが書いておられますが、自分も、
まとめてBYTEの配列に読み込んでそれをつなげながら、
文字列クラスで取り出してゆくのが良いかと思います。

キャッシュの効き具合で効果の度合いも違うかと思います。

更には、読み出し側を別スレッドにしてやると速くなります。
デッドロックしないプロダクト-コンシューマーパターンのテーブルを
ひとつご自分の自作ライブラリに加えておかれると、
今後色々使い回しが出来て便利かと思います。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-11-23 22:41
引用:

myamaさんの書き込み (2005-11-23 10:46) より:

更には、読み出し側を別スレッドにしてやると速くなります。


すみません、教えてください。
これ、どういう意味でしょう?私は、作り方によっては、ユーザインタフェースのレスポンスがよくなるだけで、読み込み処理が速くなるとは思えないのですが。逆に、作り方によっては、ユーザにレンスポンスを返しながら、実行しなければならないスレッドが増えるので、遅くなると思うのです。
___________________________________________________________________
□ written by Jitta on 2005/11/23
□ Microsoft MVP :Visual Developer ASP/ASP.NET Oct.2005-Sept.2006
_________________
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-11-23 22:45
引用:

Jittaさんの書き込み (2005-11-23 22:41) より:

逆に、作り方によっては、ユーザにレンスポンスを返しながら、
実行しなければならないスレッドが増えるので、遅くなると思うのです。


そうですね、通常「処理」は遅くなりますね。
「体感速度」に関する話だと思います。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2005-11-24 07:29
引用:

じゃんぬねっとさんの書き込み (2005-11-23 22:45) より:
引用:

Jittaさんの書き込み (2005-11-23 22:41) より:
逆に、作り方によっては、ユーザにレンスポンスを返しながら、
実行しなければならないスレッドが増えるので、遅くなると思うのです。


そうですね、通常「処理」は遅くなりますね。
「体感速度」に関する話だと思います。


いや、作り方によっては十分に早くなりますよ。HDDは低速なデバイスです。ファイルの読み込み完了を待つ間に、読み込んだデータの解析を同時に行えば、高速化できます。ファイルの読み込みを別スレッドで実行し、2行目を読み込んでいる間に、別のスレッドで1行目の解析を同時に行うわけです。WindowsAPIを使うなら非同期ファイルI/Oを使っても良いでしょう。

最近はHyperThredingやDualCoreプロセッサが採用されており、複数の論理CPUを持っていることが少なくありません。この点でも複数のスレッドに処理を分割するのは十分に有効でしょう。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-11-24 08:48
引用:

甕星さんの書き込み (2005-11-24 07:29) より:

ファイルの読み込み完了を待つ間に、読み込んだデータの解析を同時に行えば、高速化できます。


ああ、処理全体の話でしたか。
てっきり「読み込み」だけのお話かと思っていました。(;_ _)

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌

スキルアップ/キャリアアップ(JOB@IT)