また、最小要素のインデックスが必要であるとします。これに削減節を使用する方法はありますか?
残念ながら、 OpenMPの削減可能なリストは非常に小さいです。特に、min
とmax
は唯一の「上位レベル」の機能であり、カスタマイズすることはできません。まったく。
私はOpenMPの削減方法が嫌いであることを認めなければなりません。ちょうど拡張性がないからです。は特殊なケースでしか動作しません。確かに、それらは面白い特別なケースですが、それは基本的には悪いアプローチです。
このような操作では、スレッドローカル結果をスレッドローカル変数に蓄積し、最後にそれらを組み合わせることで、削減を実装する必要があります。
これを実行する最も簡単な方法は、各スレッドの要素を持つ配列を持ち、omp_get_thread_num()
を使用して要素にアクセスすることです。ただし、アレイ内の要素がキャッシュラインを共有する場合、これにより誤った共有が原因でパフォーマンスが低下します。これを軽減するには、配列を埋めてください:
struct min_element_t {
double min_val;
size_t min_index;
};
size_t const CACHE_LINE_SIZE = 1024; // for example.
std::vector<min_element_t> mins(threadnum * CACHE_LINE_SIZE);
#pragma omp parallel for
for (int i = 0; i < n; ++i) {
size_t const index = omp_get_thread_num() * CACHE_LINE_SIZE;
// operate on mins[index] …
}
私はあなたが 'omp_get_num_threads'を意味すると思いますか? – user1071136
@ user1071136いいえ、私は 'omp_get_thread_num'を意味します。総数ではなく*索引*が必要です。 'スレッドナム(threadnum) 'については、プレースホルダです。並列領域内にいないので、ここで 'omp_get_num_threads'を使うことはできません。代わりに、後続の並列節のスレッド数として実際にnumthreadを渡す必要があります。 –
+1は偽の共有に言及しています。それでも、OpenMP削減条項は、拡張性のためではなく効率性と容易な実装のために設計されています。 –