検討中:
void saxpy_worksharing(float* x, float* y, float a, int N) {
#pragma omp parallel for
for (int i = 0; i < N; i++) {
y[i] = y[i]+a*x[i];
}
}
そして
void saxpy_tasks(float* x, float* y, float a, int N) {
#pragma omp parallel
{
for (int i = 0; i < N; i++) {
#pragma omp task
{
y[i] = y[i]+a*x[i];
}
}
}
タスクとompparallelディレクティブを使用した場合の違いは何ですか?マージソートなどの再帰的アルゴリズムをタスクで記述できるのに、ワークシェアリングでは記述できないのはなぜですか?
ローレンスリバモア国立研究所のOpenMPチュートリアルをご覧になることをお勧めします ここ 。
あなたの特定の例は、OpenMPタスクを使用してnot実装されるべきではない例です。 2番目のコードはスレッドタスクの数のN
倍を作成し(欠落している}
の横にあるコードにエラーがあるため、後で戻ってきます)、各タスクは非常に単純な計算。 この質問 に対する私の回答でわかるように、タスクのオーバーヘッドは巨大になります。それに加えて、2番目のコードは概念的に間違っています。ワークシェアリングディレクティブがないため、すべてのスレッドがループのすべての反復を実行し、N
タスクの代わりに、N
倍のスレッドタスクが作成されます。次のいずれかの方法で書き直す必要があります。
シングルタスクプロデューサー-一般的なパターン、NUMAは非友好的:
void saxpy_tasks(float* x, float* y, float a, int N) {
#pragma omp parallel
{
#pragma omp single
{
for (int i = 0; i < N; i++)
#pragma omp task
{
y[i] = y[i]+a*x[i];
}
}
}
}
single
ディレクティブは、ループを単一のスレッド内でのみ実行します。他のすべてのスレッドはそれをスキップし、single
構文の最後にある暗黙のバリアにぶつかります。バリアには暗黙的なタスクスケジューリングポイントが含まれているため、待機中のスレッドは、タスクが使用可能になるとすぐに処理を開始します。
並列タスクプロデューサー-よりNUMAフレンドリー:
void saxpy_tasks(float* x, float* y, float a, int N) {
#pragma omp parallel
{
#pragma omp for
for (int i = 0; i < N; i++)
#pragma omp task
{
y[i] = y[i]+a*x[i];
}
}
}
この場合、タスク作成ループはスレッド間で共有されます。
NUMAが何であるかわからない場合は、NUMAの使いやすさに関するコメントは無視してください。