是否可以在Fortran IF语句中使用向量参数而不是标量参数

时间:2017-06-13 04:49:19

标签: fortran fortran90

如果可能的话,我想使用带有向量参数的单个IF语句,而不是使用三个连续的标量IF语句。我无法弄清楚如何。

想要这个的原因是测试它的速度。我的代码可以运行几天,调用此部分数十亿次。即使加快一点也会产生很大的不同。

这是一个带有三个IF语句的工作代码,用于虚拟场景。

program main

!==============================================
!               Define variables
!==============================================

real, dimension(10,3)         :: r                              ! 10 atoms     each with x,y,z coordinates
real, dimension(3)            :: rij                            ! x,y,z vector of difference between two atoms
real                          :: Box_Length                     ! length of simulation box
real                          :: time, timer_start, timer_end   
integer                       :: timer

!=======================================================
!                   Begin Program body
!=======================================================
Box_Length = 1.0    ! based on a box of length = 1 since coords are randomly generated between 0 and 1

!=================================
! Generate random atom coordinates
!=================================

r = 0.0
CALL RANDOM_NUMBER (r) 

!=================================
!         Begin algorithm
!=================================

call cpu_time(timer_start)

do timer = 1,30000

do i = 1,size(r)

    do j = 1, size(r)

        if(i == j) cycle

        rij(:) = abs(r(i,:) - r(j,:))

        !==============================
        ! Apply mirror image convention
        !==============================
        if(rij(1) > Box_Length - rij(1) ) rij(1) = rij(1) - Box_Length 
        if(rij(2) > Box_Length - rij(2) ) rij(2) = rij(2) - Box_Length 
        if(rij(3) > Box_Length - rij(3) ) rij(3) = rij(3) - Box_Length

        !*******************************************************************************
        !   Question: Can I make it into a single if statement i.e.                    *
        !                                                                              *
        ! if(rij(:) > Box_Length(:) - rij(:) ) rij(:) = rij(:) - Box_Length(:)         *
        !                                                                              *
        ! Where Box_Length is now a vector and only the coordinate that triggers      *
        ! the if statement is modified. Meaning that if { rij(2) >  Box_Length - rij(2) } *
        ! only rij(2) is modified, not all three.                                      *
        ! I have tried making Box_Length a vector, but that failed.                    *
        !*******************************************************************************

        ! insert rest of algorithm

    enddo ! j-loop

enddo  ! i loop

enddo   ! timer loop

call cpu_time(timer_end)

time = timer_end - timer_start

print*, 'Time taken was: ', time

end program main

感谢您将此转换为矢量化IF语句的任何帮助。另外,我在列和行向量之间来回切换。目前列向量对我来说工作得更快。这不是关于列与行向量的问题。我自己做时机并使用更快的方法。我根本无法得到一个有效的矢量方法来尝试计时。

1 个答案:

答案 0 :(得分:4)

"if(rij(:) > Box_Length(:) - rij(:) ) rij(:) = rij(:) - Box_Length(:)"

可以

where (rij > Box_Length - rij) rij = rij - Box_Length

并不是说它不会比显式DO循环更快,它只是一种更短的写入方式。它甚至可以使它变慢,因为可能会使用临时数组,或者编译器可能很难对其进行矢量化 - 在SIMD矢量化意义上。

我建议不要使用“矢量化”这个词来谈论Fortran中的速记数组符号。在Fortran中,矢量化通常意味着使用SIMD CPU指令。编译器调用该向量化。你的矢量化概念来自Python但没有在Fortran中使用,并且误导了其他读者。

另请阅读https://software.intel.com/en-us/blogs/2008/03/31/doctor-it-hurts-when-i-do-this,了解您应该仅使用rij而非rij(:)的原因。

TLDR:可以将它写在一行上,但在Fortran数组表示法中并不是使程序更快的方法。通常它会产生相反的效果。