最近,我测试了显式求和和内在函数的运行时差异来计算点积。令人惊讶的是,天真的明确的写作更快。
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
如果我使用:gfortran test.f90 -o test ; time ./test
我使用函数dot_product
(上面评论过)和 4,486s 使用手动显式写法找到 6,297s 的运行时。
这有什么意义呢?
如果我使用:gfortran test.f90 -O3 -o test ; time ./test
我发现运行时分别为 1,808s 和 1,803s 。所以两者实际上都是相同的速度。
...是更快的内在功能,因为它可以:
显式表单必须顺序:
我是否必须创建新的并行dot_product 功能才能更快?或者我不知道gfortran编译器的附加选项吗?
请注意:我在互联网上阅读有关现代Fortran中的SIMD,自动矢量化和并行化的信息。虽然我学到了什么,但我的问题在任何地方都没有得到解答。
答案 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
循环并行。