9

std::vector<size_t> buffer(100)このコードで示唆されているように、ループの並列化で各スレッドに 1 つずつbuffers を使用するつもりです。

std::vector<size_t> buffer(100);
#pragma omp parallel for private(buffer)
for(size_t j = 0; j < 10000; ++j) {
    // ... code using the buffer ...
}

このコードは機能しません。すべてのスレッドにバッファがありますが、それらのサイズは 0 にすることができます。

各スレッドの先頭にバッファを割り当てるにはどうすればよいですか? まだ使え#pragma omp parallel forますか?そして、これよりもエレガントにできますか:

std::vector<size_t> buffer;
#pragma omp parallel for private(buffer)
for(size_t j = 0; j < 10000; ++j) {
    if(buffer.size() != 100) {
        #pragma omp critical
        buffer.resize(100);
    }
    // ... code using the buffer ...
}
4

2 に答える 2

11

質問と受け入れられた回答はしばらく前から出回っています。ここでは、openMP に関する追加の洞察を提供し、他のユーザーに役立つ可能性のある追加情報をいくつか示します。

C++ では、privateandfirstprivate節はクラス オブジェクトを異なる方法で処理します。

OpenMP アプリケーション プログラム インターフェイス v3.1 から:

private : 新しいリスト項目は、初期化子なしでローカルに宣言されたかのように初期化されるか、未定義の初期値を持ちます。クラス型のさまざまなプライベート変数のデフォルト コンストラクターが呼び出される順序は規定されていません。

firstprivate : クラス型の変数の場合、リスト変数の初期化を実行するためにコピー コンストラクターが呼び出されます。

つまりprivate、デフォルトのコンストラクターをfirstprivate呼び出しますが、対応するクラスのコピー コンストラクターを呼び出します。

のデフォルトのコンストラクターはstd::vector、要素のない空のコンテナーを構築します。これが、バッファーのサイズが 0 である理由です。

質問に答えるために、これは OpenMP リージョンを分割する必要のない別のソリューションになります。

std::vector<size_t> buffer(100, 0);  
#pragma omp parallel for firstprivate(buffer)
for (size_t j = 0; j < 10000; ++j) {
  // use the buffer
}

一般に、プライベート変数に関する注意事項を編集OMP_STACKSIZEします。スレッドスタックサイズは制限されており、明示的に設定されていない限り (環境変数) コンパイラに依存します。メモリ フットプリントが大きいプライベート変数を使用すると、スタック オーバーフローが問題になる場合があります。

于 2013-12-12T09:16:58.393 に答える