私は当初は並列計算用に設計されていなかった非常に長いプログラムをスピードアップしようとしています。したがって私はgfortran
で自動並列化を試しています。gfortranとの自動並列化
私は基本的には、いくつかのループを実行し、実行時間を計測していることを、次のテストプログラムを持っている:
program autoparallel
implicit none
integer :: N = 10000
double precision, allocatable :: A(:, :), X(:), Y(:)
integer :: i, j
integer :: time_start, time_finish, time_rate
call system_clock (time_start, time_rate)
allocate(A(N, N), X(N), Y(N))
do i=1, N
do j=1, N
A(i, j) = i * j
end do
end do
do i=1, N
X(i) = i
end do
do i=1, N
Y(i) = 0.d0
end do
do i=1, N
do j=1, N
Y(i) = Y(i) + A(j, i) * X(j)
end do
end do
call system_clock (time_finish, time_rate)
write(*,*) 'Elapsed time: ', (time_finish-time_start)/real(time_rate), ' seconds'
write(*,*) Y(1), Y(N)
deallocate(A, X, Y)
end program autoparallel
私は別のコンパイラフラグで5回ずつ、それを実行:だから
gfortran test.f90
4.14799976 seconds
4.51900005 seconds
4.42399979 seconds
4.15600014 seconds
4.38000011 seconds
gfortran -floop-parallelize-all -ftree-parallelize-loops=2 autoparallel.f90
4.36899996 seconds
4.07499981 seconds
4.35599995 seconds
4.17899990 seconds
4.37500000 seconds
gfortran -floop-parallelize-all -ftree-parallelize-loops=4 autoparallel.f90
4.28399992 seconds
4.42600012 seconds
4.19999981 seconds
4.33199978 seconds
4.14499998 seconds
gfortran -O3 autoparallel.f90
3.63599992 seconds
3.63599992 seconds
3.79800010 seconds
3.55900002 seconds
3.59599996 seconds
gfortran -O3 -floop-parallelize-all -ftree-parallelize-loops=4 autoparallel.f90
3.09299994 seconds
3.08299994 seconds
3.46799994 seconds
3.00099993 seconds
3.00699997 seconds
gfortran -O3 -floop-nest-optimize autoparallel.f90
1.03100002 seconds
1.01800001 seconds
1.02300000 seconds
1.03600001 seconds
0.947000027 seconds
を基本的に実行時間はスレッドの数と平らです。最適化の後でのみ、自動並列化が開始されます。 これがなぜか理解しようとしています。
少なくともすべてのi
-loopsは、最適化を行わずに複数のスレッドに分散させることができます。
ここでは正確に何が起こっていますか?そして、私はプログラムをさらに高速化するために使用できる他のコンパイラフラグがありますか?そして、どのフラグが私の並列化の目標と矛盾しているでしょうか?
-floop-nest-optimize
は、-floop-parallelize-all
と一緒には使用できません。 エラー:
isl_constraint.c:497: position out of bounds
スマート最適化コンパイラので、したがって、それは '定義ループを気にする必要はありません、何もY' 'の値で行われていないことを理解するであろう(とはかなりスマートすることができ、コンパイラの最適化) Y 'である。同様に、「X」と「A」の定義を気にする必要がないことを認識します。そうすれば、プログラム全体がいくつかのタイマークエリといくつかの出力ステートメントに崩壊するでしょう。私はgfortranがこれを行うかどうかを調査していませんが(時間はそうではないと示唆しています)、最適化を有効にすると、あなたが思うものを実行していない可能性があります。 – IanH
最初のループはループネスト切り替えの明白な候補ですが、私はそれを自動的に見つけるためにgfortranを考慮しません。また、gfortranが最後のもので自動的にdot_productの置換を実行することも期待していません。 – tim18
deallocate()の前に "print *、Y(1)、Y(N)"を置くと、デッドコードの削除の可能性を避けることができます。 osx10.9でgfort-6.1を使用した場合、-floop-nest-optimizeを付けることで計算がほぼ2倍速くなりました@(これらの並列(?)オプションはわかりませんでしたので非常に面白いです...) – roygvib