1

私はスーパーコンピュータを使った計算電磁気研究室の研究を行っています。ここでは、500M未知数を含む問題を解決するためにクラスタを使用しています。この時点では、これらの計算をすべて並列化することに問題があります。これまではMPIを使ってノード間の通信を行ってきましたが、OpenMPを使用してノード内のプロセッサ間の通信を可能にすることをOpenMPの利点から判断しようとしています。それにもかかわらず、私たちはopenMPから効率を得ることができませんでした(おそらく、誤ったコーディングのためです)。実際には、私が与えるコードには何が間違っているのか分かりません。OpenMPと並列化の問題

OpenMPディレクティブを使用しない連続した純粋なコードでは同じ時間がかかりました。私が 'top'コマンドを使用すると、パラレルセクションの間に8つのプロセッサが%100のパフォーマンスで動作していました。

gfortran --version |ヘッド-1 GNU Fortran(GCC)4.1.2 20080704(Red Hat 4.1.2-46)

PROGRAM dotproduct 
    USE omp_lib 
    IMPLICIT none 

    INTEGER ::h,m,i,TID,NTHREADS,j,ierr 

    REAL :: start,end 
    REAL, ALLOCATABLE, DIMENSION(:,:) :: a 
    REAL, ALLOCATABLE, DIMENSION(:) :: x 
    REAL, ALLOCATABLE, DIMENSION(:) :: b 

    m= 20000 
    OPEN(UNIT=1,FILE='matrix20000.dat',STATUS='UNKNOWN') 
    OPEN(UNIT=2,FILE='vector20000.dat',STATUS='UNKNOWN') 

    ALLOCATE(a(m,m)) 
    ALLOCATE(x(m)) 
    ALLOCATE(b(m)) 
    REWIND(1) 
    REWIND(2) 

    WRITE(*,*) ' Reading is just started' 

    READ(1,*), a(:,:) 
    READ(2,*), x(:) 

    WRITE(*,*) ' Reading is over' 
    WRITE(*,*) ' Calculating will be started after parallelization' 

    !$OMP PARALLEL PRIVATE(i,TID,j),SHARED(NTHREADS,m,a,x,b) 
    TID= omp_get_thread_num() 
    IF(TID == 0) THEN 
     NTHREADS = OMP_GET_NUM_THREADS() 
     PRINT*, 'Starting matrix multiple example with', NTHREADS 
    END IF 
    CALL cpu_time(start) 
    !$OMP DO 
      DO i=1, m 
      b(i)= 0 
      DO j=1, m 
       b(i) = b(i)+ a(i,j)*x(j) 
      END DO 
      END DO 
    !$OMP END DO 
    !$OMP END PARALLEL 
    CALL cpu_time(end) 

    WRITE(*,*) end-start,' seconds' 

    !DO i=1,m 
    ! WRITE(*,*) b(i) 
    !END DO 

    DEALLOCATE(a)      !----Deallocation 
    DEALLOCATE(x) 
    DEALLOCATE(b) 


    END PROGRAM dotproduct 
+2

OMPサポート4.1は、パフォーマンスの低下のために悪名高かったのgcc RedHatにバックポートさ。私は他のことをする前に、より現代的なコンパイラを見ることをお勧めします。 – talonmies

+1

gcc 4.1がこのパフォーマンスの主な理由です。パラレル化がないように見えるので、実際には「パフォーマンスが悪い」と言うのは正しいですか。 – Yigit

+0

ちょうど私の心には、正確にランタイムを測定していますか? cpu_timeの出力を使用すると、すべてのスレッドの累積時間が取得されます。とにかくMPIを使用する場合は、代わりにMPI_wtimeを使用して実際のリアルタイムを取得する必要があります。コンパイラに関しては、GCCの実装が4.1であっても悪いとは思わないが、コンパイラを切り替えてもOpenMPスケーリングを改善する可能性がある。 – haraldkl

答えて

0

矛盾するメモリアクセスの問題のようです。すべてのプロセスが共用x(j)にアクセスします。実際の解決策ではありませんが、各スレッドでxを複製して、これが役立つかどうかを確認してください。

+0

各スレッドでxを複製するとどういう意味ですか?どうすればいいですか? – Yigit

+0

各tidに同じ内容のx(j、tid)のようなものがあります。 – haraldkl

+0

これは多分:http://people.sc.fsu.edu/~jburkardt/f_src/mxv_open_mp/mxv_open_mp.f90あなたにとって興味深いものですが、彼らはOpenMPでマトリックスベクトル乗算のワークシェアリングバージョンを持っています。 – haraldkl

1

クラシックエラー - Cpu_timeは通常、合計CPU時間を測定します。つまり、すべてのスレッドで合計されます。したがって、スレッド数に関係なく一定の時間で完璧なスピードアップが得られます

system_clockなどで壁の時間を測定してみてください。

BTW - なぜnthreadsを共有していますか?それはプライベートできるだけ多くを維持するのが最善です(...これが二回表示された場合は申し訳ありません、最初の努力)

できるだけ

関連する問題