MPI阻塞與非阻塞依據緩衝區大小不同表徵(點對點)

MPI阻塞與非阻塞依據緩衝區大小不同表徵(點對點)

MPI_Send & MPI_Isend

當傳輸的數據量小於send緩衝區大小

MPI_Send與MPI_Isend的操作一樣,都是直接返回,(Send/Isend語句之後修改源指針內容也不會對傳輸的數據產生影響)直到遇到同步點才進行同步。

當傳輸的數據量大於send緩衝區大小

MPI_Send在執行後直接阻塞,待得Recv操作完成後才能繼續執行。

MPI_Isend還是直接返回,但是Isend語句之後修改源指針內容會對傳輸數據產生影響,且對應的Recv操作只有等到MPI_Isend遇到同步障之後才能夠執行(換句話說此時的MPI_Isend並沒有將數據直接發送到接收進程的緩衝區,而是等到遇到同步障之後才進行數據的發送)

:調用MPI_Isend()之後直接返回,但是此時真正的數據傳輸是在調用MPI_Wait() / MPI_Test()等同步障之後

MPI緩衝區大小

經過測試,MPI的send緩衝區大小爲65424B,略小於64KB,所以傳輸數據爲64KB時是一個傳輸的分界線。

:測試平臺:Ubuntu MPICH / CentOS IntelMPI

​ 測試方法:多進程gdb調試法

​ 測試代碼:

int size = 65424;
if(rank == 0) { 
    isbuf[9999] = 'a';                                                             
    MPI_Send(&isbuf, size, MPI_CHAR, 1, TAG, MPI_COMM_WORLD);
    // MPI_Isend(&isbuf, size, MPI_CHAR, 1, TAG, MPI_COMM_WORLD, &request);
    isbuf[9999] = 'b'; 
} else {
    MPI_Recv(&irbuf, size, MPI_CHAR, 0, TAG, MPI_COMM_WORLD, &status);
    printf("irbuf[9999] = %c, source = %d, tag = %d, count = %d\n",
    irbuf[9999], status.MPI_SOURCE, status.MPI_TAG, count);
}  

MPI_WAIT

int MPI_Wait(
  MPI_Request *request,
  MPI_Status *status
);

當request標識的操作完成時,返回對MPI_WAIT的調用(即上述調用MPI_Isend,request所標識的操作爲另一個進程將數據Recv完畢)。MPI_WAIT爲非本地操作。同時將request(request是由非阻塞send或receive創建)關聯的通信對象釋放,並將句柄置爲MPI_REQUEST_NULL。

調用MPI_WAIT意味着可以重用用戶緩衝區

參考鏈接

[1] What is the difference between isend and issend?

[2] MPI_Wait

[3] MPI發送和接收掛起的緩衝區大小超過64kb

總結

1、在傳輸數據小於緩衝區大小時,Send與Isend操作相同,傳輸之後可以任意修改數據,且Recv操作可以直接在接收到傳輸數據後直接返回

2、在傳輸數據大於緩衝區時,Send會阻塞直到Recv操作執行完畢;而Isend操作可以直接返回,但是數據傳輸直到MPI_WAIT()才進行,所以在這之間不能修改源傳輸地址數據。

3、Recv會直接阻塞直到接收到數據,而Irecv會直接返回,待到執行MPI_WAIT才真正進行數據接收,所以不能在這之間操作目的傳輸地址數據

4、MPI_WAIT是非本地操作(不同MPI實現不同,可能通過全局結構體進行實現)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章