1

一連のデータ ファイルを生成します。ファイルは読み取り可能であると想定されているため、テキスト ファイルです(バイナリ ファイルではなく)。

ファイルに情報を出力するために、私は非常に便利なstd::ofstreamオブジェクトを使用しました。

最初は、エクスポートするデータが小さかったとき、ファイルへの書き込みに必要な時間は目立ちませんでした。ただし、エクスポートする情報が蓄積されているため、現在は生成に 5 分程度かかります。

待っていることに悩まされ始めたので、私の質問は明らかです. std::ofstreamに代わるより速い方法はありますか? より高速な代替手段がある場合、アプリケーションを書き直す価値はありますか? つまり、節約できる時間は +50% になるでしょうか? ありがとうございました。


アップデート:

上記のファイルを生成するコードを表示するように求められたので、ここに示します -最も時間のかかるループ:

ofstream fout;
fout.open(strngCollectiveSourceFileName,ios::out);

fout << "#include \"StdAfx.h\"" << endl;
fout << "#include \"Debug.h\"" << endl;
fout << "#include \"glm.hpp\"" << endl;
fout << "#include \"" << strngCollectiveHeaderFileName.substr( strngCollectiveHeaderFileName.rfind(TEXT("\\")) + 1) << "\"" << endl << endl;

fout << "using namespace glm;" << endl << endl << endl;


for (unsigned int nSprite = 0; nSprite < vpTilesetSprites.size(); nSprite++ )
{
    for(unsigned int nFrameSet = 0; nFrameSet < vpTilesetSprites[nSprite]->vpFrameSets.size(); nFrameSet++)
    {

        // display index definition
        fout << "// Index Definition: " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetLongDescription() << "\n";
        string strngIndexSignature = strngIndexDefinitionSignature;
        strngIndexSignature.replace(strngIndexSignature.find(TEXT("#aIndexArrayName#")), strlen(TEXT("#aIndexArrayName#")), TEXT("a") + vpTilesetSprites[nSprite]->GetObjectName() + vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetFrameSetName() + TEXT("IndexData") );
        strngIndexSignature.replace(strngIndexSignature.find(TEXT("#ClassName#")), strlen(TEXT("#ClassName#")), strngCollectiveArrayClassName );        
        fout << strngIndexSignature << "[4] = {0, 1, 2, 3};\t\t" << "// " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetShortDescription() << ": Index Definition\n\n";


        // display vertex definition
        fout << "// Vertex Definition: " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetLongDescription() << "\n";

        string strngVertexSignature = strngVertexDefinitionSignature;
        strngVertexSignature.replace(strngVertexSignature.find(TEXT("#aVertexArrayName#")), strlen(TEXT("#aVertexArrayName#")), TEXT("a") + vpTilesetSprites[nSprite]->GetObjectName() + vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetFrameSetName() + TEXT("VertexData") );
        strngVertexSignature.replace(strngVertexSignature.find(TEXT("#ClassName#")), strlen(TEXT("#ClassName#")), strngCollectiveArrayClassName );
        fout << strngVertexSignature << "[" << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetFramesCount() << "] =\n";
        fout << "{\n";

        for (int nFrameNo = 0; nFrameNo < vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetFramesCount(); nFrameNo++)
        {
            fout << "\t" << "{{ vec4(" << fixed << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[0].vPosition.fx << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[0].vPosition.fy << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[0].vPosition.fz << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[0].vPosition.fw << "f), vec2(" << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[0].vTextureUV.fu << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[0].vTextureUV.fv << "f) },  // " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetShortDescription() << " vertex 1: vec4(x, y, z, w), vec2(u, v) \n";
            fout << "\t" << " { vec4(" << fixed << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[1].vPosition.fx << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[1].vPosition.fy << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[1].vPosition.fz << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[1].vPosition.fw << "f), vec2(" << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[1].vTextureUV.fu << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[1].vTextureUV.fv << "f) },  // " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetShortDescription() << " vertex 2: vec4(x, y, z, w), vec2(u, v) \n";
            fout << "\t" << " { vec4(" << fixed << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[2].vPosition.fx << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[2].vPosition.fy << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[2].vPosition.fz << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[2].vPosition.fw << "f), vec2(" << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[2].vTextureUV.fu << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[2].vTextureUV.fv << "f) },  // " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetShortDescription() << " vertex 3: vec4(x, y, z, w), vec2(u, v) \n";
            fout << "\t" << " { vec4(" << fixed << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[3].vPosition.fx << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[3].vPosition.fy << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[3].vPosition.fz << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[3].vPosition.fw << "f), vec2(" << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[3].vTextureUV.fu << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[3].vTextureUV.fv << "f) }},  // " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetShortDescription() << " vertex 4: vec4(x, y, z, w), vec2(u, v) \n\n";
        }
        fout << "};\n\n\n\n";
    }
}

fout.close();
4

5 に答える 5

4

CファイルI/Oを使用したくない場合は、試してみることができます。FastFormat。詳細については、比較をご覧ください。

于 2011-06-08T02:48:11.493 に答える
3

十分な大きさのチャンクでそれを行うと仮定すると、write()を直接呼び出す方が速いかもしれません。そうは言っても、最大のボトルネックはstd::ofstreamとは直接関係がない可能性が高いです。最も明白なことは、std :: endlを使用していないことを確認することです(ストリームを頻繁にフラッシュするとパフォーマンスが低下するため)。それを超えて、アプリをプロファイリングして、実際にどこで時間を費やしているかを確認することをお勧めします。

于 2011-06-08T02:47:09.797 に答える
3

どのようvpTilesetSpritesvpTilesetSprites[nSprite]保管されていますか?それらはリストまたは配列で実装されていますか? それらへのインデックス付きアクセスが多数あり、それらがリストのような構造である場合、不要なポインターをたどるのに多くの余分な時間を費やすことになります。Ed S. のコメントは正しいです。長いインデックス付きの一時変数と改行を指定すると、読みやすくなり、おそらく速くなります。

fout << "// Index Definition: " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetLongDescription() << "\n";
string strngIndexSignature = strngIndexDefinitionSignature;
strngIndexSignature.replace(strngIndexSignature.find(TEXT("#aIndexArrayName#")), strlen(TEXT("#aIndexArrayName#")), TEXT("a") + vpTilesetSprites[nSprite]->GetObjectName() + vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetFrameSetName() + TEXT("IndexData") );
strngIndexSignature.replace(strngIndexSignature.find(TEXT("#ClassName#")), strlen(TEXT("#ClassName#")), strngCollectiveArrayClassName );        

string idxsig = strngIndexDefinitionSignature;
sprite sp = vpTilesetSprites[nSprite];
frameset fs = sp->vpFrameSets[nFrameSet];

fout << "// Index Definition: " << fs->GetLongDescription() << "\n";
idxsig.replace(idxsig.find(TEXT("#aIndexArrayName#")), strlen(TEXT("#aIndexArrayName#")),
    TEXT("a") + sp->GetObjectName() + fs->getFrameSetName() + TEXT("IndexData"));
idxsig.replace(idxsig.find(TEXT("#ClassName#")), strlen(TEXT("#ClassName#")),
    strngCollectiveArrayClassName);

しかし、はるかに大きな問題は、文字列をテンプレートとして使用する方法です。与えられたテキスト文字列を探しています (そして、必要なたびに針の文字列の長さを計算しています!)何度も何度も.

これを考慮してください: 検索と置換操作をnSprite*nFrameSet回実行しています。毎回、このループ:

  • のコピーを作成しますstrngIndexDefinitionSignature
  • 静的文字列と動的文字列を連結するときに、 4 つの一時的な文字列オブジェクトを作成します
  • 計算するstrlen(TEXT("#ClassName#"))
  • 計算するstrlen(TEXT("#aIndexArrayName#"))
  • 両方の開始点を見つける
  • 両方のテキストを新しいテキストに置き換える

これは、ループの最初の 4 行にすぎません。

strngIndexDefinitionSignatureフォーマット文字列に置き換えることはできますか? 現在、次のようになっていると思います。

"flubber #aIndexArrayName# { blubber } #ClassName# blorp"

書き直すと次のようになります。

"flubber a %s%sIndexData { blubber } %s blorp"

次に、2 つの検索と置換の行を次のように置き換えることができます。

sprintf(out, index_def_sig, sp->GetObjectName(), fs->getFrameSetName(),
    strngCollectiveArrayClassName);

find()これにより、2 つの操作、2 つのreplace()操作、4 つの一時的な文字列オブジェクトの作成と破棄、2 つのreplace()呼び出しですぐに上書きされた文字列の複製、およびstrlen()毎回同じ結果を返す2つの操作が削除されます (ただし、実際には必要ありません)。

<<その後、通常どおり文字列を出力できます。または、 に変更sprintf(3)fprintf(3)て、一時的な C 文字列を回避することもできます。

于 2011-06-08T03:31:41.563 に答える
1

のパフォーマンスostreamはおそらく実際の問題ではありません。プロファイラーを使用して、実際のボトルネックがどこにあるかを判断することをお勧めします。ostream実際の問題であることが判明した場合は、ファイルハンドルにドロップダウンして、フォーマットされた出力に<cstdio>使用できます。fprintf(FILE*, const char*, ...)

于 2011-06-08T02:48:17.600 に答える
1

最良の答えは、生成するテキストの種類と、それをどのように生成するかによって異なります。C ++ストリームは遅くなる可能性がありますが、それは主に、ロケールに依存するフォーマットなど、より多くのことを実行できるためです。

ostream::write書式設定の一部をバイパスするか(例)、代わりにストリームバフに文字を直接書き込むことで、ストリームの速度が向上する場合があります( streambuf::sputn)。関連するstreambufのバッファサイズを増やすと(を介してstreambuf::pubsetbuf)役立つ場合があります。

これだけでは不十分な場合は、Cスタイルのstdioファイル(など)を試してみてくださいfopenfprintfその方法に慣れていない場合は、テキストのフォーマット方法に慣れるまで少し時間がかかります。通常、パフォーマンスはかなり良好です。

絶対的な最高のパフォーマンスを得るには、通常、OS固有のルーチンに移動する必要があります。直接的な低レベルのファイルルーチンがCstdioよりも大幅に優れている場合もありますが、そうでない場合もあります。たとえば、Win32のWriteFileがWindowsで最速の方法であると言う人もいますが、Googleのヒットの中にはそれよりも遅いと報告している人もいます。 stdio。別のアプローチは、メモリマップトファイルです。mmap+ msync-これは基本的にシステムメモリをディスクとして使用し、実際のデータを大きなブロックでディスクに書き込みます。これはほぼ最適である可能性があります。ただし、何らかの理由で途中でクラッシュが発生した場合、すべてのデータが失われるリスクがあります。これは、問題になる場合と問題にならない場合があります。

于 2011-06-08T02:53:31.757 に答える