私はスーパーコンピュータを使った計算電磁気研究室の研究を行っています。ここでは、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
OMPサポート4.1は、パフォーマンスの低下のために悪名高かったのgcc RedHatにバックポートさ。私は他のことをする前に、より現代的なコンパイラを見ることをお勧めします。 – talonmies
gcc 4.1がこのパフォーマンスの主な理由です。パラレル化がないように見えるので、実際には「パフォーマンスが悪い」と言うのは正しいですか。 – Yigit
ちょうど私の心には、正確にランタイムを測定していますか? cpu_timeの出力を使用すると、すべてのスレッドの累積時間が取得されます。とにかくMPIを使用する場合は、代わりにMPI_wtimeを使用して実際のリアルタイムを取得する必要があります。コンパイラに関しては、GCCの実装が4.1であっても悪いとは思わないが、コンパイラを切り替えてもOpenMPスケーリングを改善する可能性がある。 – haraldkl