16

考慮:

    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];
         }
      }
   }

tasks と omp parallel ディレクティブを使用する違いは何ですか? マージソートなどの再帰アルゴリズムをタスクで記述できるのに、ワークシェアリングでは記述できないのはなぜですか?

4

1 に答える 1

29

ローレンス リバモア国立研究所の OpenMP チュートリアルを参照することをお勧めします。こちらから入手できます。

あなたの特定の例は、OpenMP タスクを使用して実装すべきではないものです。2 番目のコードはN、スレッド タスクの数の倍数を作成します (欠落している の横のコードにエラーがあるため}です。後で戻ってきます)。各タスクは非常に単純な計算のみを実行します。この質問に対する私の回答でわかるように、タスクのオーバーヘッドは膨大になります。また、2 番目のコードは概念的に間違っています。ワークシェアリング ディレクティブがないため、すべてのスレッドがループのすべての反復を実行し、タスクの代わりにNNスレッド数の倍のタスクが作成されます。次のいずれかの方法で書き換える必要があります。

シングル タスク プロデューサー - 一般的なパターン、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 の使いやすさに関するコメントを無視してください。

于 2012-10-25T12:23:51.647 に答える