本質的にシーケンシャルである単一のMCMCチェーンを並列化しようとしているため、実行される反復の順序を維持する必要があります。この目的のために、私はOpenMPを介して「orderedfor」ループを使用することを考えていました。OpenMPでの順序付きforループの実行が実際にどのように機能するのか知りたいのですが、コードの並列化に関して実際にスピードアップを提供しますか?
ありがとう!
ループに順序付けられた構造を持つブロックが1つしかない場合、実行はシリアルになり、並列実行によるスピードアップは得られません。以下の例では、並列で実行できる1つのブロックと、シリアル化される1つのブロックがあります。
void example(int b, int e, float* data)
{
#pragma omp for schedule(static) ordered
for (int i = b; i < e; ++i) {
// This block can be executed in parallel
data[i] = SomeThing(data[i]);
if (data[i] == 0.0f)
{
// This block will be serialized
#pragma omp ordered
printf("Element %d resulted in zero\n", i);
}
}
}
マルコフ連鎖が1つしかない限り、それを並列化する最も簡単な方法は、「恥ずかしい」並列処理を使用することです。多数の独立した連鎖を実行し、すべてが完了したら結果を収集します[またはしばらく。]
このようにして、通信のオーバーヘッドは一切発生しません。
ここでの主な注意点は、異なるチェーンが異なる乱数ジェネレータシードを取得することを確認する必要があるということです。
UPD:結果を収集する実用性。
一言で言えば、すべてのチェーンによって生成された結果を混ぜ合わせるだけです。簡単にするために、3つの独立したチェーンがあるとします。
x1, x2, x3,...
y1, y2, y3,...
z1, z2, z3,...
これらから、チェーンを作成します。x1,y1,z1,x2,y2,z2,x3,y3,z3,...
これは完全に有効なMCチェーンであり、正しい分布をサンプリングします。
すべてのチェーン履歴を書き出すことは、ほとんどの場合非現実的です。通常、各チェーンはビニング統計を保存します。その後、これらの統計を混合して、個別のプログラムで分析します。ビニング分析については、たとえば[boulder.research.yale.edu/Boulder-2010/ReadingMaterial-2010/Troyer/Article.pdf][1]を参照してください。
openMPの順序付きディレクティブは、動的な観点でのみリストできます。
仕様は、私たちが書く間、順序付けられたキーワードに言及しなければならないことを示唆しています。ただし、ループ内のどこに順序付けられたブロックがあるかを選択します。
私の推測では、forでorderedキーワードについて言及したとしても、各スレッドは並行して作業を開始します。順序付けられたキーワードに遭遇したスレッドは、前のすべての反復が完了した場合にのみ、このブロックに入る必要があります。以前のすべての反復を完了する必要があるキーワードに焦点を合わせてください。
上記の推論の直感は、連続して実行された場合の「注文済み」はまったく意味がないということです。