【正文】
– S:同步模式 – I:立即發(fā)送,即非阻塞方式, I可與B,R,S組合 消息發(fā)送和接收函數(shù)影響到各節(jié)點(diǎn)進(jìn)程間同步關(guān)系及程序性能,應(yīng)謹(jǐn)慎選擇使用 分類 發(fā)送 接收 阻 塞 通 信 MPI_Send MPI_Recv MPI_Irecv MPI_Recv_init MPI_Bsend MPI_Rsend MPI_Ssend 非阻塞通信 非重復(fù) MPI_Isend MPI_Recv MPI_Irecv MPI_Recv_init MPI_Ibsend MPI_Irsend MPI_ISSend 重 復(fù) MPI_Send_init MPI_Recv MPI_Irecv MPI_Recv_init MPI_Bsend_init MPI_Rsend_init MPI_Ssend_init 二、標(biāo)準(zhǔn)發(fā)送和接收 ? 標(biāo)準(zhǔn)發(fā)送和接收是阻塞式 (blocking)的 – 直到傳輸在本地完成 (locally plete)后,發(fā)送 /接收函數(shù)才返回 ? 本地完成與全局完成 – 本地完成 (locally plete) :在本地進(jìn)程中執(zhí)行的傳輸工作已經(jīng)完成 – 全局完成 (globally plete):整個(gè)傳輸已經(jīng)完成 MPI_Send():阻塞式發(fā)送消息 MPI_Recv():阻塞式接收消息 int MPI_Send( void *buffer, //發(fā)送數(shù)據(jù)指針 int count, //發(fā)送數(shù)據(jù)元素?cái)?shù) MPI_Datatype type, //發(fā)送數(shù)據(jù)類型 int dest, //目的進(jìn)程 ID int tag, //識(shí)別該消息的標(biāo)記 MPI_COMM m //MPI通信子 )。 int MPI_Recv( void *buffer, //接收數(shù)據(jù)指針 int count, //欲接收數(shù)據(jù)元素?cái)?shù) MPI_Datatype type, //接收數(shù)據(jù)類型 int source, //發(fā)送進(jìn)程 ID int tag, //識(shí)別該消息的標(biāo)記 MPI_COMM m, //MPI通信子 MPI_Status *status //接收操作狀態(tài)指針 )。 例: MPI_Send( buffer, 10, MPI_INT, 1, 123, MPI_COMM_WORLD ) 消息緩沖區(qū)指針 消息中數(shù)據(jù)個(gè)數(shù) 消息數(shù)據(jù)類型 目的進(jìn)程號(hào) tag 通信子 點(diǎn)到點(diǎn)通信 二、標(biāo)準(zhǔn)發(fā)送和接收 include include include define BUF_SIZE 10 int myid, numProcs, sbuf[BUF_SIZE], rbuf[BUF_SIZE]。 MPI_Status status。 int main( int argc, char **argv ) { int i。 MPI_Init( amp。argc, amp。argv )。 MPI_Comm_rank( MPI_COMM_WORLD, amp。myid )。 MPI_Comm_size( MPI_COMM_WORLD, amp。numProcs )。 for ( i = 0。 i BUF_SIZE。 i++ ) sbuf[i] = myid + i。 if ( myid == 0 ) ProcRecv()。 else ProcSend()。 MPI_Finalize()。 return 0。 }/*main()*/ int ProcSend() { /* 向 0號(hào)進(jìn)程發(fā)送消息 */ printf( process:%d of %d sending...\n, myid, numProcs )。 MPI_Send( sbuf, BUF_SIZE, MPI_INT, 0, 1, MPI_COMM_WORLD )。 }/*ProcSend()*/ int ProcRecv() { int source。 /* 從 0號(hào)進(jìn)程以外的每個(gè)進(jìn)程接收消息 */ printf( process:%d of %d receiving..n, myid, numProcs )。 for ( source = 1。 source numProcs。 source++ ) MPI_Recv( rbuf, BUF_SIZE, MPI_INT, source, 1, MPI_COMM_WORLD, amp。status )。 }/*ProcRecv()*/ 注意程序在多個(gè)節(jié)點(diǎn)上執(zhí)行時(shí),各節(jié)點(diǎn)上進(jìn)程的 myid值不相同 進(jìn) 程 0r a n k = 0..S e n d ( )...進(jìn) 程 1r a n k = 1進(jìn) 程 2r a n k = 2進(jìn) 程 3r a n k = 3..S e n d ( ).....S e n d ( ).....R e c v ( )...啟動(dòng) 4個(gè)進(jìn)程時(shí) 點(diǎn)到點(diǎn)通信 ? 發(fā)送消息需指明接收進(jìn)程號(hào) ? 接收方可從任意源接收消息,也可指定源進(jìn)程 – 使用參數(shù) MPI_ANY_SOURCE、MPI_ANY_TAG ? MPI通信函數(shù)使用 MPI_Status返回通信結(jié)果 typedef struct MPI_Status( int count, //發(fā)送 /接收的字節(jié)數(shù) int cancelled, int MPI_SOURCE, //通信對(duì)端的進(jìn)程號(hào) int MPI_TAG, //消息 tag int MPI_ERROR )。 ? 標(biāo)準(zhǔn)模式下的緩沖區(qū)使用 – 由 MPI環(huán)境決定是否對(duì)要發(fā)送的消息進(jìn)行緩沖 – 如果緩沖了待發(fā)送的數(shù)據(jù),則與緩沖通信模式一樣,即使接收端尚未啟動(dòng)接收操作,發(fā)送函數(shù)也可立即返回 – 出于性能和資源優(yōu)化考慮, MPI會(huì)提供一定數(shù)量的緩沖區(qū),超過緩沖區(qū)容量時(shí),發(fā)送方需要阻塞直到接收操作收取數(shù)據(jù)后才可返回 ? 阻塞式通信中,發(fā)送端完成與否不僅取決于本地進(jìn)程的狀態(tài),還與遠(yuǎn)端接收進(jìn)程的狀態(tài)有關(guān) 點(diǎn)到點(diǎn)通信 二 、 標(biāo)準(zhǔn)發(fā)送和接收 ? 阻塞式通信時(shí)發(fā)送 /接收進(jìn)程的幾種狀態(tài) ① 雙方啟動(dòng)發(fā)送和接收操作 – proc0會(huì)立即啟動(dòng)數(shù)據(jù)傳輸操作 ② 發(fā)送動(dòng)作早于接收動(dòng)作啟動(dòng) – 如消息長(zhǎng)度 緩沖區(qū), proc0需等待直到proc1啟動(dòng)接收; – 如消息長(zhǎng)度 ≤緩沖區(qū),消息存入緩沖區(qū),發(fā)送函數(shù)立即返回,但實(shí)際的消息傳輸需等到接收啟動(dòng)后才開始。 ③ 發(fā)送動(dòng)作遲于接收動(dòng)作啟動(dòng) – proc0會(huì)立即啟動(dòng)數(shù)據(jù)傳輸操作 p r o c 0 p r o c 1r e c vs e n d①p r o c 0 p r o c 1r e c vs e n d②p r o c 0 p r o c 1r e c vs e n d③ 點(diǎn)到點(diǎn)通信 三、緩沖通信模式 (Buffered) ? 用于解開阻塞式通信時(shí)發(fā)送與接收之間的耦合關(guān)系 ? 緩沖通信模式下 – 即使接收進(jìn)程沒有啟動(dòng)接收操作,發(fā)送方在將消息轉(zhuǎn)移至緩沖區(qū)后,發(fā)送函數(shù)也可返回 – 開銷:消息需在緩沖區(qū)間拷貝 – 如果消息大小超過緩沖區(qū)容量,發(fā)送函數(shù)會(huì)返回錯(cuò)誤 ? 與標(biāo)準(zhǔn)模式的區(qū)別在于: – 標(biāo)準(zhǔn)模式由 MPI環(huán)境決定是否使用緩沖,緩沖區(qū)是 MPI環(huán)境提供的,緩沖不足時(shí)發(fā)送函數(shù)將阻塞 – 緩沖通信模式由應(yīng)用程序提供緩沖區(qū),確保發(fā)送函數(shù)不阻塞 點(diǎn)到點(diǎn)通信 三、緩沖通信模式 ? 緩沖通信模式使用的幾個(gè)函數(shù) – 發(fā)送函數(shù): MPI_Bsend(),參數(shù)與 MPI_Send()相同 – 發(fā)送前使用 MPI_Pack_size()獲取消息需要的緩沖區(qū)大小,并分配緩沖區(qū) – 發(fā)送前使用 MPI_Buffer_attach()裝配緩沖區(qū) – 發(fā)送后使用 MPI_Buffer_detach()卸載緩沖區(qū) MPI_Pack_size():獲取消息所需緩沖區(qū)大小 MPI_Buffer_attach():裝配通信緩沖區(qū) MPI_Buffer_detach():卸載通信緩沖區(qū) int MPI_Pack_size( int count, //數(shù)據(jù)個(gè)數(shù) MPI_Datatype type, //數(shù)據(jù)類型 MPI_COMM m, //MPI通信子 int *size //緩沖區(qū)大小 (字節(jié)數(shù) ) )。 int MPI_Buffer_attach( void *buffer, //緩沖區(qū)地址 int count, //緩沖區(qū)大小 )。 int MPI_Buffer_detach( void *buffer, //緩沖區(qū)地址 int count, //緩沖區(qū)大小 )。 點(diǎn)到點(diǎn)通信 四、就緒通信模式 (Ready) ? 僅當(dāng)對(duì)方的接收操作啟動(dòng)并準(zhǔn)備就緒時(shí),才可發(fā)送數(shù)據(jù) – 程序員必須保證發(fā)送方發(fā)送時(shí),接收方已啟動(dòng)接收操作 – 如果違反了