0

割り当てられたメモリからディスクに大きなファイルを書き込む必要がある場合、それを行うための最も効率的な方法は何ですか?

現在、私は次のようなものを使用しています。

char* data = static_cast<char*>(operator new(0xF00000000)); // 60 GB 

// Do something to fill `data` with data

std::ofstream("output.raw", std::ios::binary).
   write(data, 0xF00000000);

しかし、さまざまなバッファリングメカニズムなどを考慮すると、最も簡単な方法が最も効率的であるかどうかはわかりません。

64ビットターゲットでWindows764ビットおよびVisualStudio2012RCコンパイラを使用しています。

4

4 に答える 4

2

Windowsの場合、CreateFileAPIを使用する必要があります。そのページと、最適化について言及しているページからのリンクをよく読んでください。バッファリングをオフにするために渡すフラグがいくつかあります。これは、過去に1秒あたり約800 MBでビデオを収集していて、その一部をRAIDアレイにできるだけ速く書き留める必要があったときに行いました。

さて、旗については-私はそれが主にこれらだと思います:

  • FILE_FLAG_NO_BUFFERING
  • FILE_FLAG_WRITE_THROUGH

読み取りには、を使用することをお勧めしますがFILE_FLAG_SEQUENTIAL_SCAN、バッファリングをオフにすると効果がないと思います。

キャッシング動作のセクションをご覧ください

あなたがしなければならないことがいくつかあります。まず、常にセクターサイズの倍数のデータ量を書き込む必要があります。これはほぼ普遍的に512バイトです(または少なくともそうでした)が、将来的には最大2048バイトを検討することをお勧めします。

次に、メモリもそのセクターサイズに合わせる必要があります。_aligned_malloc()必要以上のバッファを使用するか、単に割り当てて手動で調整することができます。

他のメモリ最適化の懸念があるかもしれません、そしてあなたは個々の書き込み操作をメモリページサイズに制限したいかもしれません。私はその深さに決して入りませんでした。それでも、ディスクの制限に非常に近い速度でデータを書き込むことができました。stdio呼び出しを使用するよりも大幅に高速でした。

バックグラウンドでこれを行う必要がある場合は、オーバーラップI / Oを使用できますが、正直なところ、私はそれを理解していませんでした。ビデオバッファの書き込み専用のバックグラウンドワーカースレッドを作成し、外部で制御しました。

于 2012-08-20T22:42:42.823 に答える
1

頭に浮かぶ最も有望なことは、出力ファイルのメモリマッピングです。データがどのように満たされるかによっては、既存のプログラムにポインタを介してディスクに直接書き込むこともでき、最後に別の書き込みステップを行う必要がない場合もあります。これは、OSがファイルを効率的にページングすることを信頼します。これは、とにかくヒープメモリに関係している可能性があります...ディスク間のコピーを回避できる可能性があります。

特にWindowsでそれを行う方法はわかりませんが、パフォーマンスをさらに向上させるために、意図したメモリアクセスパターンをOSに通知することができます。

(boost :: asioはメモリマップトファイルを移植可能にサポートしています)

于 2012-08-20T22:44:49.173 に答える
1

使用するstd::ofstream場合は、次のことを確認する必要があります。

  1. ファイルストリームはバッファを使用しません。を呼び出すためにこれを行う方法out.setbuf(0, 0)
  2. std::localeストリームによって使用される文字変換が行われないこと、つまり、std::use_facet<std::codecvt<char, char> >(loc).always_noconv()を生成しないことを確認してくださいtrue"C"ロケールがこれを行います。

これによりstd::ofstream、大きなバッファを書き込む他のアプローチと同じくらい高速になると思います。また、メモリマップドI / Oは、コンテンツを書き込むためだけに読み取るときにメモリのページングセクションを回避する必要があるため、メモリマップドI/Oを使用するよりも低速になると予想されます。

于 2012-08-20T23:12:21.613 に答える
1

でファイルを開き、をCreateFile使用SetEndOfFileしてファイル用のスペースを事前に割り当て(書き込み時に断片化しすぎないようにするため)、WriteFileファイル全体を書き込むまで、ループ内で2 MBサイズのバッファー(このサイズはほとんどのシナリオで最適に機能します)で呼び出しますアウト。

FILE_FLAG_NO_BUFFERING状況によっては役立つ場合もあれば、状況を悪化させる場合もあるため、通常はWindowsファイルシステムの書き込みキャッシュが適切に機能しているため、実際に使用する必要はありません。

于 2012-08-20T23:53:47.463 に答える