1

サイズが 1000 万を超えるベクトルをテキスト ファイルに書き込むコードがあります。私は clock() を使用して writefile 関数とプログラムの最も遅い部分の時間を計りました。以下の方法よりもファイルに書き込むためのより良い方法はありますか?

void writefile(vector<fields>& fieldsvec, ofstream& sigfile, ofstream& noisefile)
/* Writes clean and noise data to respective files
 *
 * fieldsvec: vector of clean data
 * noisevec: vector of noise data
 * sigfile: file to store clean data
 * noisefile: file to store noise data
 */
{
    for(unsigned int i=0; i<fieldsvec.size(); i++)
    {
        if(fieldsvec[i].nflag==false)
        {
            sigfile << fieldsvec[i].timestamp << ";" << fieldsvec[i].price << ";" << fieldsvec[i].units;
            sigfile << endl;
        }
        else
        {
            noisefile << fieldsvec[i].timestamp << ";" << fieldsvec[i].price << ";" << fieldsvec[i].units;
            noisefile << endl;
        }
    }
}

私の構造体は次のとおりです。

struct fields
// Stores a parsed line of a file
{
public:
    string timestamp;
    float price;
    float units;
    bool nflag; //flag if noise (TRUE=NOISE)
};
4

3 に答える 3

4

を取り除くことをお勧めしendlます。これにより、毎回バッファが効果的にフラッシュされるため、syscall の数が大幅に増加します。

'\n'代わりに書くendlことは、非常に良い改善になるはずです。

ところで、コードは単純化できます。

ofstream& files[2] = { sigfile, noisefile };
for(unsigned int i=0; i<fieldsvec.size(); i++)
  files[fieldsvec[i].nflag] << fieldsvec[i].timestamp << ';' << fieldsvec[i].price << ";\n";
于 2013-02-02T23:18:12.017 に答える
1

このSOの質問の最初の回答で示唆されているように、テキスト形式ではなくバイナリ形式でファイルを書き込んで、書き込み速度を上げることができます:

file.open(filename.c_str(), ios_base::binary);
...
// The following writes a vector into a file in binary format
vector<double> v;
const char* pointer = reinterpret_cast<const char*>(&v[0]);
size_t bytes = v.size() * sizeof(v[0]);
file.write(pointer, bytes);

同じリンクから、OP は次のように報告しました。

  • std::endl を \n に置き換えると、コード速度が 1% 向上しました
  • ストリームに書き込むすべてのコンテンツを連結し、最後にすべてをファイルに書き込むと、コード速度が 7% 向上しました
  • テキスト形式をバイナリ形式に変更したことで、コード速度が 90% 向上しました。
于 2013-02-02T23:14:27.830 に答える
0

重要な速度キラーは、数値をテキストに変換していることです。

生のファイル出力に関しては、デフォルトでのバッファリングofstreamは非常に効率的であると考えられています。

配列を const 参照として渡す必要があります。これは大したことではないかもしれませんが、特定のコンパイラーの最適化が可能になります。

書き込みが繰り返されるためにストリームが混乱していると思われる場合は、 of を使用して文字列を作成し、それを 1 回書き込むことができsprintfますsnprintf。タイムスタンプが既知のサイズである場合にのみ、これを行ってください。もちろん、文字列を出力バッファに入れる必要があるため、余分なコピーが必要になります。実験。

そうしないと、汚れ始めます。ファイルのパフォーマンスを微調整する必要がある場合は、アプリケーションに合わせてバッファーを調整する必要があります。それは、バッファリングやキャッシュを使用せず、独自のバッファをセクタで整列し、大きなチャンクを書き込むことに帰着する傾向があります。

于 2013-02-02T23:23:38.187 に答える