5

私は非常にCPUを集中的に使用する(そのprocバウンド)科学的ソフトウェアに取り組んでいますが、データをかなり頻繁にディスクに書き込む必要があります(i/oバウンド)。

私はこれ (OpenMP) に並列化を追加していますが、ディスクへの書き込みのニーズに対処する最善の方法を考えています。シミュレーションが HDD で待機する必要がある理由はありません (これが現在行われていることです)。

このための「ベスト プラクティス」を探しています。速度が最も重要です (これらは非常に長いシミュレーションになる可能性があります)。

ありがとう〜アレックス

最初の考え:

別のプロセスがディスクへの実際の書き込みを行うため、シミュレーションには 2 つのプロセスがあります。1 つは CPU バウンド (シミュレーション) で、もう 1 つは IO バウンド (ファイルの書き込み) です。これは複雑に聞こえます。

おそらくパイプ/バッファ?私はこれらに慣れていないので、おそらくそれが可能な解決策になるでしょう。

4

6 に答える 6

5

完全に新しいプロセスではなく、別のスレッドを生成してデータを保存するのが最善の方法だと思います。新しいプロセスでは、保存するデータをプロセスの境界を越えて通信しなければならないという問題が発生し、新たな一連の問題が発生します。

于 2009-06-18T17:42:40.327 に答える
3

頭に浮かぶ最初の解決策は、あなたが言ったこととほぼ同じです-シムからライターへの一方向パイプを使用して、独自のプロセスでディスクに書き込みます。ライターは可能な限り高速に書き込みます (パイプから新しいデータを引き出します)。これに関する問題は、sim がライターより先に進みすぎると、とにかくパイプ書き込みで sim がブロックされ、1 回の削除で I/O バウンドになることです。

問題は、実際にはシミュレーション サイクルが結果を吐き出すまで完了しないことです。

2 番目に思いつくのは、ノンブロッキング I/O を使用することです。シムが書き込む必要があるときはいつでも、ノンブロッキング I/O を介して行う必要があります。次に書き込みが必要になったとき、新しい I/O 操作を開始する前に、前の I/O 操作の結果を取得できます (少し待機する可能性があります)。これにより、シミュレーションが書き込みよりもはるかに先に進むことなく、I/O と並行して可能な限りシミュレーションを実行できます。

シミュレーション処理サイクルが変化する場合 (書き込み時間よりも短い場合もあれば、長い場合もある) は、最初のソリューションの方が適しています。

処理サイクルが常に (またはほとんど常に) 書き込み時間よりも短い場合は、パイプを使用する場合、最終的にいっぱいになるため、パイプを気にせず、ノンブロッキング I/O を使用することもできます。いずれにせよ、sim は I/O でハングアップします。

于 2009-06-18T17:57:35.887 に答える
2

プログラムに OpenMP を実装する場合は、#pragma omp singleまたは#pragma omp master from parallel section を使用してファイルに保存することをお勧めします。これらのプラグマは、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 つのスレッドだけです。

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

于 2009-06-20T14:10:09.413 に答える
1

あなたは CPU と IO に縛られているので: 推測してみましょう: 利用可能なメモリはまだ十分にありますよね?

その場合、ディスクに書き込む必要があるデータをメモリ内で一定の範囲までバッファリングする必要があります。通常、大量のデータを書き込む方が、小さな断片を書き込むよりもはるかに高速です。

書き込み自体の場合: メモリ マップド IO の使用を検討してください。ベンチマークを行ってからしばらく経ちましたが、前回行ったときはかなり高速でした。

また、いつでも CPU と IO を少しトレードすることができます。現在、データを何らかの生の非圧縮データとして書き込んでいると思いますよね?単純な圧縮スキームを使用して書き込まれるデータの量を減らすと、IO パフォーマンスが向上する場合があります。ZLIB ライブラリは非常に使いやすく、最も低い圧縮レベルで非常に高速に圧縮されます。これはデータの性質にもよりますが、データに多くの冗長性がある場合は、非常に粗雑な圧縮アルゴリズムでも IO バウンドの問題を解消できる可能性があります。

于 2009-06-18T17:56:53.313 に答える
0

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

于 2009-06-18T17:49:12.750 に答える
0

アプリケーションに、CPU 用とハードディスク用の2 つのスレッドを持たせます。

CPU スレッドが完了したデータをキューにプッシュし、データが入ってくるとハードディスク スレッドがそこからプルします。

このように、CPU は単にデータを取り除き、他の誰かがそれを処理できるようにし、ハード ドライブは辛抱強くキュー内のデータを待ちます。

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

于 2009-06-18T18:01:42.323 に答える