2009-06-18 2 views
5

非常にCPU負荷の高い(プロクセスされた)科学用ソフトウェアを作成していますが、/o境界)。計算集約的なタスクを実行しているときに効率的にデータをディスクに保存する

これに並列化(OpenMP)を追加していますが、ディスクへの書き込みのニーズにどのように対処するのが最適なのでしょうか。 HDDがシミュレーションを待つ必要はありません(これは現在行われています)。

私はこのために「ベストプラクティス」を探していますが、スピードは私が最も気にするものです(これは非常に長いシミュレーションです)。 1は、CPUバウンド(シミュレーション)で、もう1つはIOバウンドである:

おかげ 〜アレックス

まず思考:シミュレーションは二つの方法がありますので、別のプロセスを持つ

は、ディスクへの実際の書き込みを行います(ライティングファイル)。これは複雑に聞こえる。

おそらくパイプ/バッファ?私はこれらのことに少し慣れているので、おそらくそれが可能な解決策になるかもしれません。

答えて

2

あなたがプログラムにOpenMPのを実装する場合は、それをファイルに保存するように並列セクションからの#pragma ompの単一またはの#pragma ompのマスターを使用することをお勧めします。これらのプラグマは、1つのスレッドだけが何かを実行できるようにします。したがって、コードは次のようになります。

#pragma omp parallel 
{ 
    // Calculating the first part 
    Calculate(); 

    // Using barrier to wait all threads 
    #pragma omp barrier 

    #pragma omp master 
    SaveFirstPartOfResults(); 

    // Calculate the second part 
    Calculate2(); 

    #pragma omp barrier 

    #pragma omp master 
    SaveSecondPart(); 

    Calculate3(); 

    // ... and so on 
} 

ここでスレッドのチームは計算を行いますが、1つのスレッドだけが結果をディスクに保存します。

ソフトウェアパイプラインのようです。私はあなたがインテルスレッディングビルディングブロックライブラリからtbb :: pipelineパターンを検討することをお勧めします。 http://cache-www.intel.com/cd/00/00/30/11/301132_301132.pdf#page=25のソフトウェアパイプラインのチュートリアルを参照してください。 4.2節を読んでください。彼らは問題を解決しました。ドライブから読み取るスレッド、読み取り文字列を処理する2つ目のスレッド、ドライブに保存する3つ目のスレッドです。

5

私は、完全に新しいプロセスではなく、データを保存するために別のスレッドを生成するのが最善の方法だと思います。新しいプロセスでは、保存するデータをプロセス境界に渡す必要がなくなり、新しい一連の問題が発生します。

0

1つのスレッドは、計算集約型プロセスのステップを継続的に実行し、部分的結果のキューに部分的結果を追加します。別のスレッドは、キューから部分的な結果を絶えず削除し、それらをディスクに書き込みます。キューへのアクセスを同期させてください。キューは、リストに似たデータ構造です。最後にアイテムを追加し、アイテムを前面から削除できます。

1

あなたはCPUとIOバウンドなので、推測させてください:まだ十分なメモリがありますよね?

もしそうなら、メモリにディスクに書き込まれなければならないデータをある程度までバッファする必要があります。大量のデータを書き込むことは、通常、小さな断片を書き込むよりはるかに高速です。

書き込み自体:メモリマップIOの使用を検討してください。私がベンチマークして以来、しばらくしてきました。

また、CPUとIOをいつでも交換できます。私はあなたが現在、ある種の生の非圧縮データとしてデータを書いていると思いますよね?簡単な圧縮方式を使用して書き込むデータ量を減らすと、IOパフォーマンスが向上することがあります。 ZLIBライブラリは、操作が非常に簡単で、最も低い圧縮レベルで非常に高速に圧縮します。データの性質にもよりますが、冗長性が非常に高い場合でも非常に粗い圧縮アルゴリズムであっても、IOバウンドの問題を解消する可能性があります。

3

最初の解決策は、シムからライターまでの一方向パイプで独自のプロセスでディスク書き込みを行うことです。作者はできるだけ早く書きます(新しいデータをパイプから引き出す)。この問題は、シムがライターよりも先に進んでしまうと、シムがパイプの書き込みをブロックすることになり、1つの削除でI/Oバウンドになります。

実際、シミュレーションサイクルは結果が吐き出されるまで完了しません。

2番目の問題は、ノンブロッキングI/Oを使用することです。シムが書き込む必要があるときはいつでも、ノンブロッキングI/Oを介して行う必要があります。次に書き込む必要がある場合、新しいI/O操作を開始する前に、以前のI/O操作の結果を取得することができます(おそらく小さな待ち時間が発生する可能性があります)。これにより、I/Oと並行してできるだけ多くのシミュレーションを実行し続けることができます。

平均的に書き込みがsimに追いついている可能性があるため、シミュレーション処理サイクルが変化する(書き込み時間よりも時にはより長いことがあります)場合は、最初の解決策が適しています。

処理サイクルが常に書き込み時間よりも短くなる場合は、パイプを使用する場合はパイプを気にせず、ノンブロッキングI/Oを使用するだけですそれは最終的にいっぱいになり、シムはI/Oにとにかくハングアップします。

+0

私は、1ウェイパイプは私がその後行く方法だと思います。私はあまりにもひどくブロッキングの問題にぶつかるとは思わない。 theres多くのデータが生成されていない、私はちょうどスレッドを分離したい。 それほど多くのデータを生成していたのであれば、実際にどれくらい保持する必要があるか再考したいと思います。 – machinaut

0

スレッド(CPU用とハードディスク用)の2つがアプリケーションに作成されます。

は、CPUスレッドのプッシュは、ハードディスクスレッドは、データが入って来てからプルキューにデータを完了しました。

この方法でCPUがデータだけを取り除くと、他の誰かがそれを処理することができますし、ハードを取得しますドライブは待ち行列内のデータが忍耐強く待っています。

実装は賢明ですが、オブジェクトの共有メモリ型としてキューを実行できますが、パイプはまさにあなたが探しているものと思われます。 CPUは、必要なときにパイプに書き込むだけです。ハードディスク側では、パイプを読み取るだけで、有効なデータが得られたときはそこから進みます。

関連する問題