2017-06-13 74 views
1

而不是使用三個連續的標量IF語句我想使用帶有向量參數的單個IF語句(如果可能的話)。我無法弄清楚如何。是否有可能在Fortran 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

if語句等同於'rij = min(rij,Box_length-rij)'。我想這只是一個測試用例,在實際的代碼版本中,size(r)而不是size(r,dim = 1)的使用是正確的。因爲它有一個界限錯誤,並且正在做額外的工作。你可能能夠利用對稱性並避免看起來像'j> i'的50%冗餘工作,但這是另一個問題。 – RussF

+0

你是對的,在我的真實代碼中,事情更加簡化。我喜歡'rij = min(rij,Box_length-rij)'的想法。我試了一下,在這個虛擬例子中比三個IF或WHERE稍慢。但是,在我的主要代碼中,它似乎稍快。分子模擬中常用的方法是'rij = rij-Box_Length * ANINT(rij/BoxSize)',這種方法非常慢。它是使用三個IF語句的一半速度。 –

回答

3
"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中,數組表示法並不是使程序更快的方法。它通常具有相反的效果。

+0

(:)很好知道,雖然現在我不知道在哪裏聲明Box_Length是一個標量或向量。運行後,似乎工作。優點和缺點我猜。在沒有任何「(:)」的情況下,使用「where」的虛擬示例是最快的。然而在我的實際代碼中沒有明顯的差異。但是,「哪裏」更好看,所以就有這個元素。取代速度,化妝品獲勝。 –

+1

Box_Length的標量或數組都可以工作。我不記得如果它是數組不規則的話,我不記得規則---我相信你至少需要相同數量的元素,我猜你需要相同的等級,不記得你是否需要完全相同的形狀,或者只有至少與rij一樣多的元素---但它最終會以元素的方式工作,所以Box_Length(i)將與rij(i)匹配以適應任意的i。 – Craig

相關問題