我正在尝试加速一个非常冗长的程序,该程序最初不是为并行计算而设计的。因此,我正在尝试使用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
我用不同的编译器标志执行了五次:
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
- 循环都可以分布在多个线程上而无需任何优化。
那么这里究竟发生了什么?还有其他编译器标志可以用来进一步加速程序吗?什么标志会与我的并行化目标相冲突?
-floop-nest-optimize
无法与-floop-parallelize-all
一起使用。
错误:
isl_constraint.c:497: position out of bounds
答案 0 :(得分:0)
我发现第三个循环通常通过OpenMP REDUCTION(或者ifort上的!DIR $ DO SIMD减少)得到改善。
USE OMPLIB
....
do i=1, N
!$OMP DO SIMD REDUCTION(+:Y)
do j=1, N
Y(i) = Y(i) + A(j, i) * X(j)
end do
end do
通过一些工作,也许Y(I)可以是PRIVATE,在I循环上并行。除非工作负载很高,否则在这些简单的情况下,对于I循环并行化很少有很多改进。
YRMV