内部dot_product比a * a + b * b + c * c慢?

时间:2018-05-30 15:26:10

标签: parallel-processing fortran gfortran dot-product

最近,我测试了显式求和和内在函数的运行时差异来计算点积。令人惊讶的是,天真的明确的写作更快

  program test

  real*8 , dimension(3) :: idmat
  real*8 :: dummy(3)

  idmat=0
  dummy=0

  do i=1,3

      idmat(i)=1

  enddo

  do j=1,10**10

  !   dummy(mod(j,3)+1)=dot_product(idmat,idmat)
      dummy(mod(j,3)+1)=idmat(1)*idmat(1)+idmat(2)*idmat(2)+idmat(3)*idmat(3)

  enddo

  print*, dummy

  end program test

这让我感到困惑:

1。否-O3优化

如果我使用:gfortran test.f90 -o test ; time ./test

我使用函数dot_product(上面评论过)和 4,486s 使用手动显式写法找到 6,297s 的运行时。 这有什么意义呢?

2。包括-O3优化

如果我使用:gfortran test.f90 -O3 -o test ; time ./test

我发现运行时分别为 1,808s 1,803s 。所以两者实际上都是相同的速度。

3。我真正期待的是

...是更快的内在功能,因为它可以:

  1. 并行计算3个产品
  2. 添加3个产品
  3. 显式表单必须顺序:

    1. 计算产品1
    2. 计算产品2
    3. 计算产品3
    4. 添加3个产品
    5. 我是否必须创建新的并行dot_product 功能才能更快?或者我不知道gfortran编译器的附加选项吗?

      请注意:我在互联网上阅读有关现代Fortran中的SIMD,自动矢量化和并行化的信息。虽然我学到了什么,但我的问题在任何地方都没有得到解答。

1 个答案:

答案 0 :(得分:1)

即使查看非优化数字也没有意义。优化的数字是相同的,所以一切都很好。

“...是更快的内在功能,因为它可以:并行计算3个产品”

除非您启用特定的并行优化,否则不会并行执行任何操作。这些优化对于循环和内在循环一样容易,并且通常更容易循环。

好吧,至少对于使用线程或类似的 parallel 的正常意义。可以并行完成的是使用向量指令并调度指令以在CPU流水线中重叠。这可以通过优化编译器完成,并且可能在您使用-O3时对两个版本都完成。如果未启用优化,则不应期望这种情况发生。

使用!$omp simd!$DEC VECTOR等编译器指令有时可以改善“并行”指令(SIMD)的使用。

“我是否必须创建一个新的并行dot_product函数才能更快?”

是的,通常你这样做。例如,使用OpenMP。或者你可以:

“或者我还不知道gfortran编译器的其他选项吗?”

是的,自动并行化https://gcc.gnu.org/wiki/AutoParInGCC,例如-floop-parallelize-all -ftree-parallelize-loops=4

请注意,它不会并行进行单独的乘法,它会使i循环并行。