我已經寫了一個函數,返回一個向量A,等於稀疏矩陣Sparse與另一個向量F的乘積。矩陣的非零值在Sparse(nnz),rowind(nnz)和colind(nnz)每個都包含Sparse每個特定值的行和列。通過do kx下的兩行矢量化(現在註釋的)內部循環相對簡單....我看不出如何矢量化外部循環,因爲pos對於不同的kx具有不同的大小。fortran向量化的極限
問題是:外部循環(do kx = 1,nxy)是否可以被矢量化,如果是,怎麼辦?
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%
弗拉基米爾F正確地推測說我來自Python /八度世界。由於我解決的PDE變得越來越大,我已經(移回)fortran以獲得更多的性能。在半小時前,矢量化意味着擺脫do循環,fortran看起來非常擅長:節省的時間用於替換「內部循環」(do ky = 1,size(pos)..)上面兩行很驚人。我在調用-fopt-info時查看gfortran(真正的gcc?)給出的信息,並且經常使用循環修改。我將立即閱讀關於SIMD和數組表示法。請,如果有關於這個話題的好消息,請讓我知道。
在回覆Holz時,存儲稀疏矩陣的方法很多,通常會導致操作符的等級降低1:我製作的示例涉及在某個字段中的每個位置評估的強制和解矢量,因此具有等級1.那麼與(S,如在A = S.F)相關的算子是二維BUT稀疏。它以這種方式存儲,只保留非零值。如果S中有nnz個非零值,那麼與S相當的稀疏Sp就是Sp(1:nnz)。如果pos表示某個數字Sp(pos)的該序列內的位置,則原始矩陣S中的列和行位置由colind(pos)和rowind(pos)給出。
在這樣的背景下,我可能會擴大問題:什麼是最好的(通過執行時間測量)可以完成乘法?
pure function SparseMul(Sparse,F) result(A)
implicit none
integer (kind=4),allocatable :: pos(:)
integer (kind=4) :: kx,ky ! gp counters
real (kind=8),intent(in) :: Sparse(:),F(:)
real (kind=8),allocatable :: A(:)
allocate(A(nxy))
do kx=1,nxy !for each row
pos=pack([(ky,ky=1,nnz)],rowind==kx)
A(kx)=sum(Sparse(pos)*F(colind(pos)))
!!$ A(kx)=0
!!$ do ky=1,size(pos)
!!$ A(kx)=A(kx)+Sparse(pos(ky))*F(colind(pos(ky)))
!!$ end do
end do
end function SparseMul
你究竟是什麼意思* vectorize *?數組表示法或SIMD內在函數?我假設前者,但請確認。關於Fortran矢量化通常意味着後者。 –
一個很好的經驗法則是並行化外部,向量化SIMD的內部。 SIMD可以更好地處理參考位置的打包數據。您可能可以將外部循環變成「for all」或添加OMP指令。正如你正在取得一筆款項,霍爾姆斯的減少操作建議是一個很好的建議。 – Davislor
從這個例子中,我確信OP在[tag:vectorization]下的含義比你和@Holmz在他的回答中(見我的第一條評論)要好。另請參見http://stackoverflow.com/questions/44075566/vectorized-array-comparison-in-fortran中的討論作爲數組符號的* vectorization *的概念在Python中被廣泛使用。 –