2012-12-10 84 views
0

MPI2允許我們創建派生的數據類型,並通過編寫堆積MPI派生數據類型的Fortran

call mpi_type_create_indexed_block(size,1,dspl_send,rtype,DerType,ierr) 
call mpi_send(data,1,DerType,jRank,20,comm,ierr) 

通過這樣的位置dspl_send 數據(N)由MPI發送給他們圖書館。現在

,對於矩陣數據(M,N)我們可以通過下面的代碼發送其位置:

call mpi_type_create_indexed_block(size,M,dspl_send,rtype,DerTypeM,ierr) 
call mpi_send(data,1,DerTypeM,jRank,20,comm,ierr) 

即條目數據(i,dspl_send(J))是發送。

我的問題涉及1在後續mpi_send中的作用。它一直是1嗎?另一個尺寸可能嗎? MPI衍生的數據類型在互聯網上的許多文檔中都有很好的解釋,但如果允許使用其他大小,並且可以如何使用,那麼send/recv中的大小總是爲。

如果我們想要使用矩陣數據(M,N),其大小M因調用而異,我們是否需要始終在調用它時創建派生數據類型?是不可能使用DerType用於發送的矩陣數據(M,N)數據(N,M)

回答

2

每個MPI數據類型都有兩個屬性:大小和範圍。大小是數據類型表示的實際字節數,而extent是數據類型在內存中覆蓋的字節數。某些數據類型不是連續的,這意味着它們的大小可能小於它們的範圍,例如, (這裏示出以僞代碼)

MPI_TYPE_VECTOR(count = 1, 
       blocklength = 10, 
       stride = 20, 
       oldtype = MPI_INTEGER, 
       newtype = newtype) 

創建一個數據類型,它採取第一10(blocklength)從總共20(stride)的元素。該數據類型的大小爲MPI_INTEGER的大小的10倍,在大多數系統上計數爲40字節。其範圍是大多數系統的兩倍大或80字節。如果count是2,那麼它將需要10個元素,然後跳過下一個10,然後再取10個元素並再次跳過下一個10.因此,它的大小和擴展會大兩倍。

當您在任何MPI例程中指定某個元素數時,例如MPI執行如下操作:

  1. 它使用源緩衝區參數的地址初始化內部數據緩衝區。
  2. 它查閱數據類型類型映射來決定有多少字節以及從何處獲取並將它們附加到正在構建的消息中。所添加的字節數等於數據類型的大小
  3. 它將內部數據指針遞增範圍的數據類型。
  4. 它減少內部計數,如果它仍然非零,重複前面的兩個步驟。

MPI的一個非常漂亮的特性是數據類型的範圍不需要與其大小相匹配(如向量示例所示),並且甚至可以賦予數據類型所需的任何範圍值MPI_TYPE_CREATE_RESIZED。這允許創建非常複雜的數據訪問模式。例如,使用MPI_SCATTERV通過不跨整行(C)或列(Fortran)的塊分散矩陣需要使用這種調整大小的類型。

回到矢量圖例。無論您是使用count = 1創建矢量類型,然後使用count = 2MPI_SEND聯繫,也可以使用count = 2創建矢量類型,然後使用count = 1MPI_SEND聯繫,最終結果是相同的。通常會構造一個數據類型來完整地描述想要發送的對象。在這種情況下,在MPI_SEND的電話中給出count = 1。但有些情況下,創建僅描述部分對象的數據類型(例如單個部件)可能更有益,然後將MPI_SENDcount設置爲想要發送的部件數量。有時候這是個人喜好的問題,有時候這是一個算法要求。

至於最後一個問題,Fortran以列主要順序存儲矩陣,這意味着data(i,j)在內存中的data(i±1,j)旁邊,而不是data(i,j±1)。因此,data(M,N)N個連續的列向量組成,每個元素爲M。兩個元素之間的距離,例如data(1,1)data(1,2)取決於M。這就是爲什麼你在類型構造函數中提供M的原因。具有不同行數的矩陣(例如,不同的M)不會「適合」所創建的類型的類型映射,並且將使用錯誤的元素來構造該消息。

+0

謝謝,這澄清了一些問題。但是,我仍然有** openmpi ** –

0

關於https://stackoverflow.com/a/13802243/7784768中程度的描述並不完全正確,因爲範圍沒有考慮到數據類型末尾的填充。 MPI數據類型被定義類型映射:然後

typemap = ((type_0, disp_0), ..., (type_n−1, disp_n−1)) 

程度根據

lb = min(disp_j) 
ub = max(disp_j + sizeof(type_j)) + e) 
extent = ub - lb, 

其中e可以是非零的,由於對準要求限定。

這意味着,在該示例

MPI_TYPE_VECTOR(count = 1, 
       blocklength = 10, 
       stride = 20, 
       oldtype = MPI_INTEGER, 
       newtype = newtype) 

與計數= 1,類型映射是

((int, 0), (int, 4), ... (int, 36)) 

和程度是在大多數系統40,而不是80(即步幅具有用於類型映射沒有影響在這種情況下)。對於計數= 2,類型映射將是

((int, 0), (int, 4), ... (int, 36), (int, 80), (int, 84), ... (int, 116)) 

和程度120(對於10個整數,步幅40個字節,而對於10個整數第二塊40個字節的第一個塊40個字節,但剩餘的步幅在程度上被忽略)。可以很容易地找出MPI_Type_get_extent函數的範圍。

範圍是一個相當棘手的概念,並且在嘗試傳達派生數據類型的多個元素時很容易出錯。

+2

歡迎。不要將公式用作「上述」,因爲答案的順序經常發生變化。現在你的答案在頂部。 –