我試圖ISend()
兩個數組:arr1,arr2
和整數n
這是arr1,arr2
大小。我從這個post瞭解到,發送一個包含全部三個結構的結構不是一個選項,因爲n
只在運行時才知道。顯然,我需要首先接收n
,否則接收過程不知道要接收多少個元素。什麼是最有效的方法來實現這一點,而不使用blokcing Send()
?ÇMPI多個動態數組傳遞
回答
發送陣列的大小是冗餘的(且低效的)作爲MPI提供了一種探測進入的消息而沒有接收它們,這在爲了正確地分配存儲器僅提供足夠的信息。探測執行MPI_PROBE
,看起來很像MPI_RECV
,除了它沒有緩衝區相關的參數。探測操作返回一個狀態對象,然後可以查詢可以從消息內容中提取的給定MPI數據類型的元素數量,其中MPI_GET_COUNT
,因此顯式發送元素數量變得多餘。
下面是一個簡單的例子有兩個等級:
if (rank == 0)
{
MPI_Request req;
// Send a message to rank 1
MPI_Isend(arr1, n, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, &req);
// Do not forget to complete the request!
MPI_Wait(&req, MPI_STATUS_IGNORE);
}
else if (rank == 1)
{
MPI_Status status;
// Wait for a message from rank 0 with tag 0
MPI_Probe(0, 0, MPI_COMM_WORLD, &status);
// Find out the number of elements in the message -> size goes to "n"
MPI_Get_count(&status, MPI_DOUBLE, &n);
// Allocate memory
arr1 = malloc(n*sizeof(double));
// Receive the message. ignore the status
MPI_Recv(arr1, n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
MPI_PROBE
還接受通配符排名MPI_ANY_SOURCE
和通配符標籤MPI_ANY_TAG
。然後可以查閱狀態結構中的相應條目,以便找出實際的發送者等級和實際的消息標籤。
探測消息大小的工作原理是每個消息都帶有一個標頭,稱爲包絡線。信封由發送者的等級,接收者的等級,消息標籤和通信者組成。它還包含有關總郵件大小的信息。信封作爲兩個通信過程之間的初始握手的一部分發送。
首先,您需要爲rank 0的arr1和arr2分配內存(full memory = n = elements),即您的前端處理器。
根據編號將數組分成若干部分。的處理器。確定每個處理器的元件數量。
發送該元件從等級0
第二發送是用於陣列即ARR1算到其它處理器和ARR2
在其它處理器根據從元件主收到的計分配ARR1和ARR2處理器即rank = 0.在接收到元素數後,接收分配的內存中的兩個數組。
這是一個示例C++實現,但C將遵循相同的邏輯。也只是交換髮送Isend。
#include <mpi.h>
#include <iostream>
using namespace std;
int main(int argc, char*argv[])
{
MPI::Init (argc, argv);
int rank = MPI::COMM_WORLD.Get_rank();
int no_of_processors = MPI::COMM_WORLD.Get_size();
MPI::Status status;
double *arr1;
if (rank == 0)
{
// Setting some Random n
int n = 10;
arr1 = new double[n];
for(int i = 0; i < n; i++)
{
arr1[i] = i;
}
int part = n/no_of_processors;
int offset = n % no_of_processors;
// cout << part << "\t" << offset << endl;
for(int i = 1; i < no_of_processors; i++)
{
int start = i*part;
int end = start + part - 1;
if (i == (no_of_processors-1))
{
end += offset;
}
// cout << i << " Start: " << start << " END: " << end;
// Element_Count
int e_count = end - start + 1;
// cout << " e_count: " << e_count << endl;
// Sending
MPI::COMM_WORLD.Send(
&e_count,
1,
MPI::INT,
i,
0
);
// Sending Arr1
MPI::COMM_WORLD.Send(
(arr1+start),
e_count,
MPI::DOUBLE,
i,
1
);
}
}
else
{
// Element Count
int e_count;
// Receiving elements count
MPI::COMM_WORLD.Recv (
&e_count,
1,
MPI::INT,
0,
0,
status
);
arr1 = new double [e_count];
// Receiving FIrst Array
MPI::COMM_WORLD.Recv (
arr1,
e_count,
MPI::DOUBLE,
0,
1,
status
);
for(int i = 0; i < e_count; i++)
{
cout << arr1[i] << endl;
}
}
// if(rank == 0)
delete [] arr1;
MPI::Finalize();
return 0;
}
謝謝!但你怎麼能確定接收沒有發生之前發生? – Shmoopy
當您執行Send/Recv時,程序將啓動處理器的句柄。 recv句柄等待相應的發送。該程序根據定義的參數(如data_type,no)匹配發送和接收。傳遞的元素,最重要的是你有一個用戶定義的「標籤」,它可以幫助映射這些語句。 Irecv/Isend和Recv/Send的唯一區別在於後面的代碼會阻止代碼的執行直到找到它的匹配部分,而Irecv/Isend放置一個句柄並繼續移動到代碼的其餘部分。 – DOOM
@DOOM,您關於匹配過程的陳述不正確。 MPI只匹配與接收方指定的包絡過濾器一起發送的消息信封,並且只包括髮件人的等級,標籤和通信器。匹配消息時,不會使用數據類型和緩衝區大小。 –
@Histro我想說的是,Irecv/Isend是MPI lib自己操縱的一些函數。你問的問題完全取決於你關於Send/Recv之後你做什麼的代碼的其餘部分。有兩種情況:
碩士和工 您發送的問題的一部分(比如數組)的工人(所有其他隊伍除了0 =主)。工作人員(在數組上)做了一些工作,然後將結果返回給主人。然後主人將結果加起來,並將新工作傳達給工人。現在,在這裏您希望主人等待所有工作人員返回他們的結果(修改後的數組)。所以你不能使用Isend和Irecv,而是在我的代碼和相應的recv中使用多重發送。如果你的代碼在這個方向上,你想使用B_cast和MPI_Reduce。
懶法師 主分工,但不小心從他的工人的結果。假設你想爲相同的數據編程一個不同類型的模式。就像給定某個城市的人口特徵一樣,你想要計算的模式包括18歲以上有多少人,有多少人有工作,有多少人在某些公司工作。現在這些結果與彼此沒有任何關係。在這種情況下,您不必擔心工作人員是否收到數據。主人可以繼續執行其餘的代碼。這是使用Isend/Irecv安全的地方。
- 1. C++傳遞一個動態數組到
- 2. 上傳和傳遞動態數組(C++)
- 3. 傳遞多個動態數組到PHP一些隱藏
- 4. 傳遞動態數組入參數
- 5. 動態數組傳遞給函數
- 6. 傳遞動態數組後,我創建這個動態數組在C
- 7. 動態傳遞php數組到javascript
- 8. 傳遞動態數組的功能
- 9. 傳遞動態數組:空值
- 10. 傳遞數據反應組件動態
- 11. Vue.js動態組件 - 傳遞數據
- 12. 傳遞結構的動態數組C++
- 13. 將動態多維數組的元素傳遞給一個函數
- 14. 傳遞一個動態創建的數組作爲參數
- 15. 傳遞一個二維動態數組在C++函數
- 16. 如何動態地將多個參數傳遞給函數?
- 17. ViewChildren傳遞多個組件
- 18. 傳遞多個數組; ajax到webmethod
- 19. 傳遞一個多維數組在C++
- 20. 傳遞多個數組來查看
- 21. 將多維數組從一個活動傳遞到另一個
- 22. 傳遞動態參數
- 23. 動態傳遞AJAX參數
- 24. 動態傳遞參數
- 25. 傳遞多維數組C++
- 26. Lua傳遞多維數組
- 27. 傳遞數組以便在C/C++中動態聲明數組
- 28. 如何傳遞一個動態數組參考c + +
- 29. Pro * C將一個動態數組傳遞給PL/SQL過程
- 30. 將動態數據傳遞給Internet Explorer - 創建多個登錄
MPI_PROBE塊操作嗎?我會想象它。 – Shmoopy
@Shmoopy,'MPI_PROBE'是一個阻塞操作。 'MPI_IPROBE'不會阻塞並返回一個布爾標誌,指示匹配的消息是否立即可用。 –