• ベストアンサー

sscanfより速い方法について。

ただいま、テキストから書式付のデータを取得するコードを 書いております。 しかし、異常にその処理が遅いので、原因を調べてみると どうやらsscanfが原因らしいということが分かりました。 問題の箇所は以下のようになっております。 char*textBuf = NULL ・・・ (textBufにテキストの内容をロード) ・・・ for(int i=0;i<vertexNum ;++i ) {  float x, y, z;/*頂点座標になります*/  /*どうやらココが遅いようです。*/  sscanf( textBuf, "%f %f %f", &x, &y, &z );  vertexs_.push_back( Vector3(x, y, -z) );  textBuf = nextLine(textBuf);/*次の行に進みます。*/ } テキストには座標が格納してありそのフォーマットは 0.0 1.4 5.4 7.1 4.2 2.3 ・・・ のようになっております。 上記の方法では5000頂点の取得に12sec近くかかり とても使用に耐えられません。 何か解決方法をご存知の方がいらっしゃいましたら ご教授よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • aid-u
  • ベストアンサー率75% (22/29)
回答No.7

環境が記述されていないのですが、どのような環境で確認されたのでしょうか。 手元の環境でsscanfを5000回繰り返すだけのプログラムを作成し、 時間を計測しましたが0.1秒もかかりませんでした。 環境は以下の通りです。  ・Windows XP上のVMWare PlayerでUbuntu 8.04を動作  ・CPUはT2300@1.66GHz  ・メモリは512MB  ・コンパイラはgcc 4.2.3 見ていただいて分かると思いますが、性能が期待できる環境ではありません。 この環境で0.1秒かからないものが、12秒かかるというのは以下のどちらかではないかと思います。  ・通常のPCではない(組み込み系?)の環境  ・sscanf以外の部分に時間がかかっている(のを見落としている) よろしければ、確認された環境を教えてください。

qatatatfds
質問者

お礼

計測ありがとうございます。 まず環境ですが、 ・OS:xp sp3 ・cpu:athlon 64×2 4400+ (2.31G Hz) ・コンパイラ:VC9 ・メモリ:1G 至って普通の環境ですね。。。 もっと小さい状況にしてみようと思い #include <cstdio> #include <stdlib.h> #include <windows.h> #pragma comment(lib, "winmm.lib") int main() { const char*data = "0.15487 0.488949 1.54897"; char*dataHuge = new char[1024*128];/*128MB*/ memset(dataHuge, 0, sizeof(char)*1024*128 ); strcpy(dataHuge, data); long start = timeGetTime(); for(int i=0;i<5000;++i) { volatile int x, y, z; sscanf(dataHuge, "%f %f %f", &x, &y, &z); } long elapse = timeGetTime() - start; printf("time:%f\n", (float)elapse*0.001f); delete []dataHuge; } としたところ、0.05secとなりました。 本来はだいぶ速い処理のようですね。。。 何か見当違いの質問をしてしまったようです。 すいません。他の部分を見てみる事にします。

qatatatfds
質問者

補足

解決しましたので、ここにて説明します。 今回はtextBufが100M近くありました。 これが原因だと考え、これを行ごとに別の 文字列に区切った後にsscanfに渡したところ 先ほどの実験程度の速度がでました。 いわゆるペンキ塗りのアルゴリズムに 起因する原因だったようです。 皆様、ご協力ありがとうございました。

その他の回答 (6)

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.6

文字列→浮動小数点変換の重い内部処理ロジックはほとんど同じなのでsscanfで遅いものがstrtodで早くなるとは思えません。このままだと解決しない可能性が高いので、どうして12秒掛かったらマズイかを教えてください。根本的な仕様が間違っている気がします。 操作性が悪くなるとか、5秒ぐらいで処理しないと何かに間に合わないとか使用に耐えれない詳しい理由をお願いします。

qatatatfds
質問者

補足

申し訳ありません。その点も説明不足でした。 まずこれはゲームに利用するモデルデータの 読み込みを行う部分になります。 最終的には2~3万頂点前後の処理を行う予定なのですが、 上の結果だと48秒以上かかってしまいます。 (頂点の他に面の情報も取得しなければならないので状況は もっと悪くなります) 「NowLoading」を流せばいい問題(?)でもあり、 明確に何秒だから不味いというものでもないのですが、 1分近い間待たせるのもいかかがなものか思っています。 最初の段階で、一秒かからない処理だと思ったものが 10秒以上かかってしまったために、酷く重大な欠陥があるような 気がしたため、質問したというのもあります。 あと、strtod,atofに関してですが、おっしゃるとおり全く速度に影響が ありませんでした。(詳しく図ればsscanfの方が速そうですが) 私も今は根本的な部分にミスがあると思います。 もう少しだけ回答を募ったらあきらめて、 他の手段を模索しようと思います。

  • Quant
  • ベストアンサー率18% (23/122)
回答No.5

No.3です。 失礼しました。 sscanfが遅いとは考えられなかったので、ファイルの読み込みで同じようにループしているのではないかと勝手に推測しました。

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.4

>#3さん >ディスクからの読み込みは遅いのでforループを5000回繰り返せば遅くなります。 くだんのforループの中でディスクからの読込みを行なっているわけではなさそうです。 >(textBufにテキストの内容をロード) の箇所は、くだんのforループの外にあります。

  • Quant
  • ベストアンサー率18% (23/122)
回答No.3

ディスクからの読み込みは遅いのでforループを5000回繰り返せば遅くなります。forループを使わず、頂点座標を構造体の5000個の配列としてfreadで一回に読み込めばいいのではないですか。

qatatatfds
質問者

お礼

返答ありがとうございます。 別の方が指摘していますが、 ロードはループの外で行っております。 またフォーマットも既に決まっており変更不可の状態です。 (コンバーターを作成するといったことは考えておりません。)

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.2

>しかし、異常にその処理が遅いので、原因を調べてみると >どうやらsscanfが原因らしいということが分かりました。 原因を調べた方法を教えてください。

qatatatfds
質問者

補足

申し訳ありません。説明不足でした。 検証方法ですが、 単純に vertexs_.push_back( Vector3(x, y, -z) ); textBuf = nextLine(textBuf);/*次の行に進みます。*/ を取り除き sscanf( textBuf, "%f %f %f", &x, &y, &z ); だけの速度を計測しました。(for(int i=0;i<vertexNum ;++i )の分だけ)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

本当に sscanf 「だけ」の時間なのかどうかわからないのでなんとも, なんですが, strtod を使って自力で処理すればいいのかもしれない. とはいえプロセッサがわからんので, 実はこれが限界という可能性もないとはいえない.

qatatatfds
質問者

お礼

返答ありがとうございます。 strtodですか..... ちょっとやってみます。

関連するQ&A