我對使用MPI相當陌生。我的問題如下:我有一個2000行和3列存儲爲二維數組的矩陣(不是連續的數據)。在不改變數組結構的情況下,根據進程數np,每個進程應該得到矩陣的一部分。 示例: 答:2000列數組的二維數組3列,np = 2,然後P0得到A的前半部分,它將是前1000行3列的二維數組,P1得到後半部分第二個1000行乘3列。 現在NP可以是任何數字(只要它劃分行數)。任何簡單的方法來解決這個問題? 我將不得不使用FORTRAN 90來完成這項任務。 感謝您的Fortran二維數組的分解矩陣以便每個進程都可以使用MPI獲取其矩陣的份額
回答
逐行分佈是使用分散棘手的(但不是不可能)/聚集的直接,因爲列主存儲操作。有兩種可能的解決方案
純粹的Fortran 90解決方案:使用Fortran 90,您可以指定像A(1:4,2:3)
這樣的陣列部分,這會從矩陣A
中取出一個小的4x2塊。您可以將數組切片傳遞給MPI例程。請注意,當前的MPI實現(符合現在的舊MPI-2.2標準)時,編譯器會創建部分數據的臨時連續副本,並將其傳遞給MPI例程(因爲臨時存儲器的生命週期尚未定義好, 不應該傳遞數組部分到非阻塞MPI操作,如MPI_ISEND
)。 MPI-3.0引入了新的和非常現代的Fortran 2008接口,它允許MPI例程直接採用數組節(無需中間數組),並支持將節傳遞給非阻塞調用。
隨着陣列部分你只需要實現在根處理的簡單DO
循環:
INTEGER :: i, rows_per_proc
rows_per_proc = 2000/nproc
IF (rank == root) THEN
DO i = 0, nproc-1
IF (i /= root) THEN
start_row = 1 + i*rows_per_proc
end_row = (i+1)*rows_per_proc
CALL MPI_SEND(mat(start_row:end_row,:), 3*rows_per_proc, MPI_REAL, &
i, 0, MPI_COMM_WORLD, ierr)
END IF
END DO
ELSE
CALL MPI_RECV(submat(1,1), 3*rows_per_proc, MPI_REAL, ...)
END IF
純MPI溶液(還與FORTRAN 77):首先,必須聲明的矢量數據類型與MPI_TYPE_VECTOR
。塊的數量爲3
,塊長度爲每個進程應得到的行數(例如1000
),步幅應該等於矩陣的總高度(例如2000
)。如果此數據類型被稱爲blktype
,那麼下面將發送矩陣的上半部分:
REAL, DIMENSION(2000,3) :: mat
CALL MPI_SEND(mat(1,1), 1, blktype, p0, ...)
CALL MPI_SEND(mat(1001,1), 1, blktype, p1, ...)
調用MPI_SEND
與blktype
將採取從指定的起始地址1000
元素,然後跳到下一個2000 - 1000 = 1000
元素,採取另一種1000
依次類推,3
次。這將形成大矩陣的1000行子矩陣。
您現在可以運行一個循環來爲通信器中的每個進程發送一個不同的子塊,從而有效地執行分散操作。爲了獲得這個子塊,在接收過程可以簡單地註明:
REAL, DIMENSION(1000,3) :: submat
CALL MPI_RECV(submat(1,1), 3*1000, MPI_REAL, root, ...)
如果你是新的MPI,這是所有你需要知道有關的Fortran由行散射矩陣。如果您很清楚MPI的類型系統是如何工作的,那麼請繼續閱讀以獲得更優雅的解決方案。
(見here關於如何通過喬納森·德西這樣做與MPI_SCATTERV
一個很好的說明。他的解決方案涉及按列分割C矩陣,這在本質上提出了和C一樣的問題,因爲C以行主要方式存儲矩陣。 Fortran版本如下。)
您也可以利用MPI_SCATTERV
,但它是相當複雜的。它建立在上述純MPI解決方案的基礎上。首先,您必須將blktype
數據類型調整爲新類型,其範圍等於MPI_REAL
,以便可以指定數組元素中的偏移量。這是必要的,因爲MPI_SCATTERV
中的偏移量是以指定的數據類型的範圍的倍數指定的,並且blktype
的範圍是矩陣本身的大小。但是由於存儲的跨越,兩個子塊將僅以4000
字節開始(1000
倍MPI_REAL
的典型範圍)。要修改型的程度,一個將使用MPI_TYPE_CREATE_RESIZED
:
INTEGER(KIND=MPI_ADDRESS_KIND) :: lb, extent
! Get the extent of MPI_REAL
CALL MPI_TYPE_GET_EXTENT(MPI_REAL, lb, extent, ierr)
! Bestow the same extent upon the brother of blktype
CALL MPI_TYPE_CREATE_RESIZED(blktype, lb, extent, blk1b, ierr)
這將創建一個新數據類型,blk1b
,其具有blktype
所有特性,例如可用於發送整個子塊,但在陣列操作中使用時,MPI只會將數據指針的大小改爲單個MPI_REAL
而不是整個矩陣的大小。使用這種新類型,您現在可以在mat
的任何元素上定位每個塊的開始位置MPI_SCATTERV
,包括任何矩陣行的開始。例如具有兩個子塊:
INTEGER, DIMENSION(2) :: sendcounts, displs
! First sub-block
sendcounts(1) = 1
displs(1) = 0
! Second sub-block
sendcounts(2) = 1
displs(2) = 1000
CALL MPI_SCATTERV(mat(1,1), sendcounts, displs, blk1b, &
submat(1,1), 3*1000, MPI_REAL, &
root, MPI_COMM_WORLD, ierr)
這裏所述第一子塊的位移是0
,其與基質的開始一致。第二子塊的位移是1000
,即它將從第一列的第1000行開始。在接收端,數據計數參數是3*1000
元素,它與子塊類型的大小相匹配。
- 1. Matlab - 將矩陣乘以3D矩陣的每個矩陣
- 2. 以矩陣形式獲得矩陣行
- 3. 使用MPI矩陣乘法
- 4. 將矩陣的每列乘以另一個矩陣
- 5. 乘以矩陣中的每一行由另一個矩陣
- 6. 使用numpy,是否可以使用其他矩陣定義矩陣?
- 7. 矩陣分解
- 8. 如何轉換矩陣,以便我可以使用ggplot
- 9. 矩陣乘法MPI
- 10. 張量流可以使用矩陣矩陣嗎?
- 11. MPI分區矩陣成更小的矩陣
- 12. 使用R中的apply()矩陣乘以三個矩陣列表?
- 13. 將矩陣分解爲初等矩陣
- 14. 以矩陣劃分,其第一值的每個列值
- 15. 乘以2D矩陣的一維矩陣
- 16. 將矩陣的每一行乘以矩陣
- 17. 乘以3D矩陣和2D矩陣CUDA
- 18. 完成一個矩形矩陣,以便產生幾個方形可逆的井狀矩陣
- 19. 我可以分解一個大規模的相關矩陣嗎?
- 20. 使用CUDA + MPI的矩陣乘法
- 21. 分矩陣爲n個矩陣
- 22. 將矩陣分成10個子矩陣
- 23. 程序乘以矩陣
- 24. 如果世界矩陣和相機矩陣都是單位矩陣,它們是否可以省略?
- 25. MPI C SendRecV矩陣乘法
- 26. 矩陣乘法與mpi
- 27. 如何用openMaya將矩陣乘以另一個矩陣?
- 28. 乘以矩陣C++
- 29. 矩陣乘以組
- 30. 以稀疏矩陣
你指的是這個嗎? http://stackoverflow.com/questions/10788180/sending-columns-of-a-matrix-using-mpi-scatter – dreamcrash
@dreamcrash - 絕對!我會鏈接到它。 –
@lleiv:哇,很好的回答!非常感謝! –