我有一段时间试图弄清楚如何在英特尔ifort编译器v16编译的Fortran代码上进行简单的Dot Product计算并行处理。我有以下代码部分,它是部分用于更复杂过程的程序,但这是程序花费大部分时间的地方:
double precision function ddot(n,dx,incx,dy,incy)
c
c forms the dot product of two vectors.
c uses unrolled loops for increments equal to one.
c jack dongarra, linpack, 3/11/78.
c modified 12/3/93, array(1) declarations changed to array(*)
c
double precision dx(*),dy(*),dtemp
integer i,incx,incy,ix,iy,m,mp1,n
c
CALL OMP_SET_NUM_THREADS(12)
ddot = 0.0d0
dtemp = 0.0d0
if(n.le.0)return
if(incx.eq.1.and.incy.eq.1)go to 20
c
c code for unequal increments or equal increments
c not equal to 1
c
ix = 1
iy = 1
if(incx.lt.0)ix = (-n+1)*incx + 1
if(incy.lt.0)iy = (-n+1)*incy + 1
do 10 i = 1,n
dtemp = dtemp + dx(ix)*dy(iy)
ix = ix + incx
iy = iy + incy
10 continue
ddot = dtemp
return
c
c code for both increments equal to 1
c
c
c clean-up loop
c
20 m = mod(n,5)
if( m .eq. 0 ) go to 40
!$OMP PARALLEL DO
!$OMP& DEFAULT(NONE) SHARED(dx,dy,m) PRIVATE(i)
!$OMP& SCHEDULE(STATIC)
!$OMP& REDUCTION( + : dtemp )
do 30 i = 1,m
dtemp = dtemp + dx(i)*dy(i)
30 continue
!$OMP END PARALLEL DO
if( n .lt. 5 ) go to 60
40 mp1 = m + 1
!$OMP PARALLEL DO
!$OMP& DEFAULT(NONE) SHARED(dx,dy,n,mp1) PRIVATE(i)
!$OMP& SCHEDULE(STATIC)
!$OMP& REDUCTION( + : dtemp )
do 50 i = mp1,n,5
dtemp = dtemp + dx(i)*dy(i) + dx(i + 1)*dy(i + 1) +
* dx(i + 2)*dy(i + 2) + dx(i + 3)*dy(i + 3) + dx(i + 4)*dy(i + 4)
50 continue
!$OMP END PARALLEL DO
60 ddot = dtemp
return
end
我是OpenMP命令的新手,我很确定我在那里有一些有趣的东西,比整个单核更慢。目前我已经尝试在较慢的4(4)核心机器上的4个线程上运行它,它实际上比我们指定12个线程用于处理的大型20(40)核心机器快一点。在这一点上,我认为代码很有趣并做了我不想要的事情。
更高的Do循环也可以并行化,但我不知道如何定义ix
和iy
,所以只留下它,因为它没有花太多时间在那里。
精度非常重要,因此编译器设置为fp-mode精确。我不知道这是否重要,但是当代码确实设法生成答案时,它们看起来是正确的。基本上,我只是想弄清楚如何加速这段代码,而是并行处理似乎会减慢这个过程。
答案 0 :(得分:1)
您可以通过一系列英特尔网络研讨会帮助您。
我有光圈优化直方图代码,可以执行OpenMP SIMD REDUCTION。所以我决定将向量引入(大,nthreads)数组,并在并行区域中执行每个线程。通常它比仅使用单个核心运行得慢。 (我还没试过vtune)
使用FFT的其他类似阵列方法运行速度更快,并且核心都是100%且具有良好的缩放率。
基本上,要么需要解决问题,要么测试哪个更好。任何OpenMP并行都需要很长时间才能启动,所以你想要它在外面,而不是在最紧张的水平上。
通常,您可以通过PURE功能或子程序以及使用
获得更好的效果!DEC$ ATTRIBUTES VECTOR ...
在ifort16中还有VECTOR(REF(变量)),引用是新的。 一旦歌唱完毕,就可以尝试平行。
你的DO 50需要为'i'提供一些大数字才能使并行化代码更快,或者OpenMP并行“启动”会占用太多时间。
除了vtune之外,没有什么可以帮助找到cashe misses(等等)让你深入了解如何获得更快的代码(实际上是没有减速的代码)。毕竟,那么使用gfortran进行编译也许是值得的。我通常发现通过两个编译器可以更深入地了解如何制作更好的整体代码。但如果你从!DEC $ Extensions获得收益,那么gfortran可能无济于事。 CONTIGUOUS也值得尝试功能。