Multithreading 点积的并行处理

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

我花了很长时间试图弄明白如何在英特尔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 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,我只是从未使用过它。我将不得不研究它的文件。