Multithreading 点积的并行处理
我花了很长时间试图弄明白如何在英特尔iFortran编译器v 16编译的Fortran代码上并行处理一个简单的点积计算。我有下面的代码部分,它是用于更复杂过程的程序的一部分,但这是程序花费大部分时间的地方:Multithreading 点积的并行处理,multithreading,parallel-processing,fortran,intel,Multithreading,Parallel Processing,Fortran,Intel,我花了很长时间试图弄明白如何在英特尔iFortran编译器v 16编译的Fortran代码上并行处理一个简单的点积计算。我有下面的代码部分,它是用于更复杂过程的程序的一部分,但这是程序花费大部分时间的地方: 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
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模式精度。我不知道这是否重要,但当代码确实能够生成答案时,它们确实看起来是正确的。基本上,我只是想弄清楚如何加速这段代码,但并行处理似乎反而会减慢这段代码的速度。有很多英特尔网络研讨会,你可以查阅它们来帮助你 我有一个光圈最佳直方图代码,可以减少OpenMP SIMD。所以我决定将向量引入一个(大的n个线程)数组,并在一个并行区域中执行每个线程。一般来说,它的运行速度比只使用一个内核要慢。(我还没有试过vtune) 使用FFT的其他类似阵列方法运行得更快,并且核心都是100%,具有良好的扩展性 基本上,一个人要么需要解决问题,要么测试哪个更好。任何OpenMP并行程序都需要很长的启动时间,因此您希望它位于外部,而不是在最紧的级别 通常,使用纯函数或子例程以及使用
!DEC$ ATTRIBUTES VECTOR ...
在ifort16中还存在向量(REF(variable)),并且引用是新的。
一旦所有这些都在歌唱,那么就可以尝试进行类比
为了使并行化代码运行得更快,您的DO 50需要一些大的“i”数字,否则OpenMP并行“启动”将占用太多时间
除了vtune之外,没有什么其他工具可以帮助您查找现金未命中(etc),让您深入了解如何获得更快的代码(这实际上是一种没有速度减慢的代码)。在所有这些之后,使用gfortran进行编译可能是值得的。我通常发现,通过运行两个编译器,可以更深入地了解如何生成更好的总体代码。但如果你从中获得收益!DEC$扩展,那么gfortran可能没有帮助。连续也值得在函数中尝试。Uf,我建议您使用
END DO
而不是CONTINUE
,读取代码非常困难。Intel已经在MKL库中为您完成了所有加快linpack ddot的工作。除其他事项外,这包括放弃5的展开,并针对多个目标体系结构进行优化。您可能会看到,单线程simd简化使用了数千个大小(dot_产品可以处理较小的情况)。fp model precise防止优化缩减,以避免用户无法控制精度的微小改进。。。“向量内部”“平行外部”。我会把它从“并行执行”改为“执行SIMD”。如果有什么东西可以得到,那么平行线就是最外面的部分。VI部分很简单,但是任何缓存未命中都会使速度变慢。如果您有iPort,您有vtune吗?谢谢您的评论,内容丰富,非常有用。是的,这都是基于我同事使用的一些代码。我的任务是尽可能地实现现代化。我将尝试切换到SIMD,我计划在下一步中使用一个更大的外部循环,因此我将在下一步中尝试并行。事实证明,我确实有vtune,我只是从未使用过它。我将不得不研究它的文件。