采用MPI_Send 和MPI_Recv 編寫代碼來實現包括MPI_Bcast、MPI_Alltoall、MPI_Gather、MPI_Scatter 等MPI 群集通信函數的功能


本文引自百度文庫

一、實驗內容

1、采用MPI_Send 和MPI_Recv 編寫代碼來實現包括MPI_Bcast、MPI_Alltoall、MPI_Gather、MPI_Scatter 等MPI 群集通信函數的功能。

2、給出抽象的並行算法描述、程序源代碼及運行時性能加速圖表。

二、抽象並行算法描述

ⅰ、MPI_Bcast算法描述:

輸入:並行處理器個數ProcessNumber

輸出:所有進程收到來自Root進程的消息

Procedure MPI_Bcast_a

Begin

對所有處理器同時執行如下的算法:

(1)if 進程為Root進程

(1.1)將message寫入消息緩沖

(1.2)for index=0 to size-1 do

              向index發送相同的message消息

          end for

(2)進程不是Root進程

(2.1)接收消息

End

2、MPI_Alltoall算法描述:

輸入:並行處理器個數ProcessNumber

輸出:所有進程收到來自其他進程不同的消息

Procedure MPI_Alltoall_a

Begin

對所有處理器同時執行如下的算法:

(1)將message寫入消息緩沖

(2)for index=0 to size-1 do

       分別向index發送不同的message消息

   end for

(3)for source=0 to size-1 do

       接收來自source的message消息

   end for

End

3、MPI_Gather算法描述:

輸入:並行處理器個數ProcessNumber

輸出: Root進程從通信域Comm的所有進程接收消息

Procedure MPI_Gather_a

Begin

對所有處理器同時執行如下的算法:

(1)if 進程為Root進程

(1.1)for source=0 to size-1 do

              接收來自source的message消息

          end for

(2)向Root進程發送自己的消息

End

4、MPI_Scatter算法描述:

輸入:並行處理器個數ProcessNumber

輸出:向所有進程發送不同的消息

Procedure MPI_Scatter_a

Begin

對所有處理器同時執行如下的算法:

(1)if 進程為Root進程

(1.1)將message寫入消息緩沖

(1.2)for index=0 to size-1 do

              向index發送不同的message消息

          end for

(2)進程不是Root進程

(2.1)接收消息

End

 

三、程序源代碼

#include "mpi.h" /*MPI head file*/

#include <stdio.h>

#include <string.h>

#define ProNum 4

void MPI_Bcast_a(int rank,int size,int tag){  //

        int index;

        char message[100];

        MPI_Status status;

        if (rank==0){

                strcpy(message,"Hello,the message is from process root!\n ");

                for(index=0;index<size;index++){

                        MPI_Send(message,strlen(message), MPI_CHAR, index, tag, MPI_COMM_WORLD); /*sending data to node#1*/

                }

                printf("There are %d processes in the group.\n",size);

        }

        else{

                MPI_Recv(message,100, MPI_CHAR, 0, tag, MPI_COMM_WORLD, &status);

                printf("Process %d received %s\n",rank,message);

        }

}

void MPI_Alltoall_a(int rank,int size,int tag){  //

        int index,source;

        char message[100];

        char buffers[ProNum][100];//if buffers *[100],there will be errors.

        char buffer[10];

        MPI_Status status;

        strcpy(message,"Hello,the message is from process ");

        //message="Hello,the message is from process ";

        snprintf(buffer,10,"%d",rank);

        strcat(message,buffer);

        for(index=0;index<size;index++){

                MPI_Send(message,strlen(message), MPI_CHAR, index, tag, MPI_COMM_WORLD); /*sending data to node#1*/

        }

        printf("There are %d processes in the group.\n",size);

        for(source=0;source<size;source++){

                MPI_Recv(buffers[source],100, MPI_CHAR,source, tag, MPI_COMM_WORLD, &status);

                printf("Process %d received %s\n",rank,buffers[source]);

        }

}

void MPI_Gather_a(int rank,int size,int tag){  //

        int index,source;

        char message[100];

        char buffers[ProNum][100];// 

        char buffer[10];

        MPI_Status status;

        strcpy(message,"Hello,the message is from process ");

        //message="Hello,the message is from process ";

        snprintf(buffer,10,"%d",rank);

        strcat(message,buffer);              

        MPI_Send(message,strlen(message), MPI_CHAR, 0, tag, MPI_COMM_WORLD); /*sending data to node#1*/    

        printf("There are %d processes in the group.\n",size);

        if(rank==0){

                for(source=0;source<size;source++){

                        MPI_Recv(buffers[source],100, MPI_CHAR,source, tag, MPI_COMM_WORLD, &status);

                        printf("Process %d received %s\n",rank,buffers[source]);

                }

        }

}

void MPI_Scatter_a(int rank,int size,int tag){  //

        int index,source;

        char message[100];

        //char buffers[ProNum][100];//if buffers *[100],there will be errors.

        char buffer[10];

        MPI_Status status;

        strcpy(message,"Hello,the message is to process ");

        //message="Hello,the message is from process ";

        if(rank==0){

                for(index=0;index<size;index++){

                        snprintf(buffer,10,"%d",index);

                        strcat(message,buffer);

                        MPI_Send(message,strlen(message), MPI_CHAR, index, tag, MPI_COMM_WORLD); /*sending data to node#1*/

                }

        }

        printf("There are %d processes in the group.\n",size);

        MPI_Recv(message,100, MPI_CHAR,0, tag, MPI_COMM_WORLD, &status);

        printf("Process %d received %s\n",rank,message);

}

int main( int argc, char** argv )

{

        int rank, size,index, tag=1;

        int senddata,recvdata;

        MPI_Status status;

        MPI_Init(&argc, &argv); /*initializing */

        MPI_Comm_rank(MPI_COMM_WORLD, &rank); /*Process#*/

        MPI_Comm_size(MPI_COMM_WORLD, &size); /*Total processes#*/

        MPI_Bcast_a(rank,size,tag);

        MPI_Alltoall_a(rank,size,tag);

        MPI_Gather_a(rank,size,tag);

        MPI_Scatter_a(rank,size,tag);

        MPI_Finalize(); /*quit from MPI world*/

        return (0);

}

四、實驗結果對比

實驗進行了相關數據的對比,主要將數據分為兩組進行對比(1)在曙光4000A上的自編寫的函數(2)在曙光4000A上使用系統自帶的函數。

實驗結果數據如下表:

(1)MPI_Bcast:

運行時間(s) 處理器個數

Real time

user CPU time

system CPU time

MPI_Bcast

實驗程序

MPI_Bcast

實驗程序

MPI_Bcast

實驗程序

2

 

0.403

 

0.041

 

0.078

4

 

0.618

 

0.071

 

0.112

8

 

1.224

 

0.123

 

0.187

16

 

1.876

 

0.205

 

0.361

32

 

3.618

 

0.390

 

0.722

64

 

6.804

 

0.702

 

1.175

表1 MPI_Bcast運行性能

(2)MPI_Alltoall:

運行時間(s) 處理器個數

Real time

user CPU time

system CPU time

MPI_Alltoall

實驗程序

MPI_Alltoall

實驗程序

MPI_Alltoall

實驗程序

2

 

0.439

 

0.050

 

0.072

4

 

0.630

 

0.066

 

0.107

8

 

1.151

 

0.109

 

0.198

16

 

1.998

 

0.233

 

0.353

32

 

7.323

 

0.439

 

0.674

64

 

17.233

 

0.881

 

1.441

表2 MPI_Alltoall運行性能

(3)MPI_Gather:

運行時間(s) 處理器個數

Real time

user CPU time

system CPU time

MPI_Gather

實驗程序

MPI_Gather

實驗程序

MPI_Gather

實驗程序

2

 

 

 

 

 

 

4

 

 

 

 

 

 

8

 

 

 

 

 

 

16

 

 

 

 

 

 

32

 

 

 

 

 

 

64

 

 

 

 

 

 

表3 MPI_Gather運行性能

(4)MPI_Scatter:

運行時間(s) 處理器個數

Real time

user CPU time

system CPU time

 

 

 

 

 

 

2

 

 

 

 

 

 

4

 

 

 

 

 

 

8

 

 

 

 

 

 

16

 

 

 

 

 

 

32

 

 

 

 

 

 

64

 

 

 

 

 

 

表4 MPI_Scatter運行性能

五、實驗結果

上圖為測試輸出時所產生結果圖,表明各個線程所接收數據並且輸出的相應過程,在數據字段填充的是各個發送端ID信息,用於驗證信息是否發送正確。爭對該程序如果信息發送正確那么在輸出報文的get * Process data:* 兩處應該是相同的。

 

圖1 MPI_Bcast接收信息顯示

 

圖2 MPI_Alltoall接收信息顯示

圖3 MPI_Gather接收信息顯示

圖4 MPI_Scatter接收信息顯示

六、程序運行時性能加速圖表

圖5 兩種情況下MPI_Bcast時間花費對比圖

圖6 兩種情況下MPI_Alltoall時間花費對比圖

圖7 兩種情況下MPI_Gather時間花費對比圖

圖8 兩種情況下MPI_Scatter時間花費對比圖

 

七、實驗分析

經過上述實驗得出的結論有以下幾點(1)曙光4000A平台上運行程序的速度很高;(2)自編寫函數性能低於系統自帶函數,但是在自編寫的Alltoall函數測試中,線程數目低於8時,自編寫Alltoall函數花費時間小於系統自帶的Alltoall函數的測試時間。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM