2012-05-14 12 views
5

OpenMPを使用して簡単なアプリケーションを作成しようとしています。残念ながら私はスピードアップに問題があります。 このアプリケーションでは、whileループが1つあります。このループの本体は、シーケンシャルに実行されるべき命令と、ループのためのものとからなる。私は#pragma omp parallel forを使ってこれをループ並列にします。このループはあまり働いていませんが、非常に頻繁に呼び出されます。OpenMP - スレッドを一度だけ作成する

私は2つのバージョンのforループを準備し、1,2および4コアでアプリケーションを実行します。
バージョン1(forループの4回の反復):22秒、23秒、26秒。
バージョン2(forループで100000反復):20秒、10秒、6秒。

ご覧のとおり、forループがあまり効果がない場合、2コアと4コアの時間は1コアよりも長くなります。 私はその理由は、#pragma omp parallel forがwhileループの各繰り返しで新しいスレッドを作成するからです。ですから、私はあなたに質問したいと思います - スレッドを一度(whileループの前に)作成し、whileループの中のいくつかのジョブが順次実行されるようにする可能性はありますか?

#include <omp.h> 
#include <iostream> 
#include <math.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <time.h> 
int main(int argc, char* argv[]) 
{ 
    double sum = 0; 
    while (true) 
    { 
     // ... 
     // some work which should be done sequentially 
     // ... 

     #pragma omp parallel for num_threads(atoi(argv[1])) reduction(+:sum) 
     for(int j=0; j<4; ++j) // version 2: for(int j=0; j<100000; ++j) 
     { 
      double x = pow(j, 3.0); 
      x = sqrt(x); 
      x = sin(x); 
      x = cos(x); 
      x = tan(x); 
      sum += x; 

      double y = pow(j, 3.0); 
      y = sqrt(y); 
      y = sin(y); 
      y = cos(y); 
      y = tan(y); 
      sum += y; 

      double z = pow(j, 3.0); 
      z = sqrt(z); 
      z = sin(z); 
      z = cos(z); 
      z = tan(z); 
      sum += z; 
     } 

     if (sum > 100000000) 
     { 
      break; 
     } 
    } 
    return 0; 
} 

答えて

5

あなたはwhile (true)ループの外側に並列領域を移動してのみ1つのスレッドで実行するコードの連続部分を作るためにsingleディレクティブを使用することができます。これにより、fork/joinモデルのオーバーヘッドが削除されます。また、OpenMPは非常に少数の反復(バージョン1など)のthightループではあまり役に立ちません。基本的には、ループ内での作業が非常に速いため、OpenMPのオーバーヘッドを測定しています。超越関数を使用した100000回の反復でも、現在の世代のCPUは2秒未満です(2 GHzではFP以外のインストラクションではなく、約100msかかる)。

#omp parallel for ... if(loopcnt > 10000) 
for (i = 0; i < loopcnt; i++) 
    ... 

通常のforループschedule(static)を使用することも賢明である(つまり、その内のすべてのforループです:OpenMPのは、選択的に小さなループに並列化をオフにするために使用することができますif(condition)句を提供する理由です

反復処理にはほぼ同じ時間がかかります)。

8

ほとんどのOpenMP実装では、プログラムの起動時に多数のスレッドが作成され、プログラムの実行中はそれらを保持します。つまり、ほとんどの実装では、実行中にスレッドを動的に作成および破棄することはありません。そのようにすると、スレッド管理に重大なコストがかかるため、パフォーマンスが低下します。スレッド管理のこのアプローチは、OpenMPの通常の使用例と一貫しており、適切です。

OpenMPスレッドの数を増やしたときに減速するのは、ループの並列回数が非常に少ないためです。 Hristoの答えはこれをカバーしています。

関連する問題