4

私はここにいくつかのものを置いて、孤児化を機能させようとしています#pragma omp parallel. 私がしようとしているのは次のようなものです:

#pragma omp parallel default(none) shared(mat,mat2,f,max_iter,tol,N,conv) private(diff,k)
{
#pragma omp master // I'm not against using #pragma omp single or whatever will work
{
while(diff>tol) {
    do_work(mat,mat2,f,N);
    swap(mat,mat2);
    if( !(k%100) ) // Only test stop criteria every 100 iteration
         diff = conv[k] = do_more_work(mat,mat2);
    k++;
} // end while
} // end master
} // end parallel

は前のdo_work反復に依存するため、while ループは順次実行する必要があります。しかし、「do_work」を並行して実行できるようにしたいので、次のようになります。

void do_work(double *mat, double *mat2, double *f, int N)
{
int i,j;
double scale = 1/4.0;
#pragma omp for schedule(runtime) // Just so I can test different settings without having to recompile
for(i=0;i<N;i++)
    for(j=0;j<N;j++)
         mat[i*N+j] = scale*(mat2[(i+1)*N+j]+mat2[(i-1)*N+j] + ... + f[i*N+j]);
} 

これが何らかの方法で達成できることを願っていますが、方法がわかりません。ですから、私が得ることができるどんな助けも大歓迎です (また、これが不可能だと言っている場合も)。ところで、私は open mp 3.0、gcc コンパイラ、sun studio コンパイラを使用しています。

4

1 に答える 1

7

元のコードの外側の並列領域には、シリアル部分(#pragma omp master)のみが含まれています。これは意味がなく、純粋にシリアル実行(並列処理なし)になります。前の反復にdo_work()依存しますが、並行して実行する場合は、同期を使用する必要があります。そのためのopenmpツールは、(明示的または暗黙的な)同期バリアです。

例(あなたと同様のコード):

#pragma omp parallel
for(int j=0; diff>tol; ++j)    // must be the same condition for each thread!
#pragma omp for                // note: implicit synchronisation after for loop
  for(int i=0; i<N; ++i)
    work(j,i);

暗黙的な同期によりj、現在のスレッドでまだ作業中のスレッドがある場合、次のスレッドに入らないようにすることに注意してくださいj

代替案

for(int j=0; diff>tol; ++j)
#pragma omp parallel for
  for(int i=0; i<N; ++i)
    work(j,i);

単に同期するのではなく、反復ごとに新しいスレッドチームが作成されるため、効率が低下するはずです。

于 2013-01-17T18:01:08.100 に答える