2017-03-17 46 views
2

我正在使用MPI實現分佈式圖像(灰度)卷積。我現有的模式是在根進程中將圖像作爲一維扁平數組讀取,然後將它們分散到所有進程(行分解),然後在根進程中執行一個MPI_Gather,然後將該圖像再次寫入爲一維扁平化陣列。顯然,這並沒有給出預期的結果,因爲在圖像卷積時,情況在邊界處變得棘手。MPI中的鬼細胞交換模式

因此,爲了提高在上述模式,我想要實現所謂的ghost cell exchange圖案,其中的過程中ghost rows.僞代碼交換他們行:

if (rank == 0) { 
    src = null 
    dest = rank + 1 
} 

if (rank == size - 1) { 
    src = rank - 1 
    dest = null 
} else { 
    src = rank - 1 
    dest = rank + 1 
} 

MPI_SendRecv(&sendbuf[offset], slen, dest.. 
      &recvbuf[offset], rlen, src); 

如何分配內存「鬼行「在每個過程?我應該預分配內存然後分散嗎?我不想去「自定義數據類型」解決方案,因爲這對我正在考慮的問題的範圍來說太過於誇張。

回答

2

理想情況下,重影單元應與您的單元格一樣是同一個內存塊的一部分。這樣,你可以保持尋址方案簡單。在該方案中,圖像通過使用MPI_ScatterMPI_Gather的多個完整行來分佈。在非邊界排名中,您爲兩個額外的幻影行分配足夠的內存:

height = total_hight/ranks; 
std::vector<float> data(width * (height + 2)); 
float* image = &data[width]; 
float* ghost_north = &data[0] 
float* ghost_south = &data[width * (height + 1)] 
float* inner_north = image; 
float* inner_south = &image[width * (height - 1)] 
MPI_Scatter(root_image, width * height, MPI_FLOAT, 
      image, width * height, MPI_FLOAT, ...); 
... 
iterations { 
    MPI_SendRecv(inner_north, width, MPI_FLOAT, north, tag, 
       ghost_north, width, MPI_FLOAT, north, tag, ...) 
    MPI_SendRecv(inner_south, width, MPI_FLOAT, south, tag, 
       ghost_south, width, MPI_FLOAT, south, tag, ...) 
    ... compute ... 
} 
MPI_Gather(image, width * height, MPI_FLOAT, 
      root_image, width * height, MPI_FLOAT, ...); 

此僞碼不考慮特殊的邊框情況。

簡單的一維分裂的問題是通信成本和額外的暈數據是非最優的。特別是對於較小的圖像和更多的參與隊伍。

這是關於使用MPI的數據分解和暈環通信方法的excellent example by Rolf Rabenseifner。他還解釋瞭如何改進溝通方法。對於二維分解,您需要派生MPI數據類型以用於初始通信和垂直邊界。

+0

感謝您提供完整,明確的答案。你提到了一些關於通信成本的內容。現在,如果我要在增加圖像尺寸時測試這個模型,那麼我的表現應該會降低,對吧? –

+0

基本上,一維分解的通信成本將比二維分解*差。通信開銷取決於圖像大小(較大=較好),等級數量(較少=較好)和每次迭代的計算(更多=較好)的平衡。 – Zulan

+0

我同意那部分,第1d溝通會涉及很多交流。感謝你的幫助。我會盡快接受答案 –