2012-06-28 6 views
6

minreduction句を持つことが可能です:は、アレイ内の最小限の要素を検索し、OpenMPの3.1とのインデックス

double m; 
#pragma omp parallel for reduction(min:m) 
for (int i=0;i< n; i++){ 
    if (a[i]*2 < m) { 
    m = a[i] * 2; 
} 
return m; 

は、私はまた、最小限の要素のインデックスを必要とし、これにはreduction句を使用する方法がありますか?私は代わりに、nowaitcriticalを使って手作業で減量を書いていると思います。

答えて

5

また、最小要素のインデックスが必要であるとします。これに削減節を使用する方法はありますか?

残念ながら、 OpenMPの削減可能なリストは非常に小さいです。特に、minmaxは唯一の「上位レベル」の機能であり、カスタマイズすることはできません。まったく。

私は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] … 
} 
+0

私はあなたが 'omp_get_num_threads'を意味すると思いますか? – user1071136

+0

@ user1071136いいえ、私は 'omp_get_thread_num'を意味します。総数ではなく*索引*が必要です。 'スレッドナム(threadnum) 'については、プレースホルダです。並列領域内にいないので、ここで 'omp_get_num_threads'を使うことはできません。代わりに、後続の並列節のスレッド数として実際にnumthreadを渡す必要があります。 –

+0

+1は偽の共有に言及しています。それでも、OpenMP削減条項は、拡張性のためではなく効率性と容易な実装のために設計されています。 –

関連する問題