簡體   English   中英

在過程之間傳遞子矩陣

[英]Passing submatrix between processes

首先,我正在從https://computing.llnl.gov/tutorials/mpi/學習消息傳遞接口(MPI)

在創建自己的MPI數據類型時,我遇到了麻煩。

我的程序正在嘗試獲取每個象限。 說出以下4 x 4矩陣,

A = {    
      1.0, 2.0,  3.0, 4.0,
      5.0, 6.0,  7.0, 8.0,
      9.0, 10.0, 11.0, 12.0,
      13.0, 14.0, 15.0, 16.0
    } 

因此,我想將其划分為4個子矩陣,以便當master發送3個子矩陣(子矩陣1、2、3)時,每個工作人員都可以接收到其各自的子矩陣。

Submatrix 0 |  Submatrix 1
Submatrix 2 |  Submatrix 3

現在,我的程序僅獲取每個子矩陣的第一行,並將第二行打印為零。

以下是當前的打印輸出。 (您可以忽略子矩陣0)

3 4
0 0 

9 10 
0 0 

11 12 
0 0 

附件是我的程序。 任何指針將不勝感激。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<mpi.h>

//matrix size
#define SIZE 4

double A[SIZE][SIZE] ={
    1.0, 2.0, 3.0, 4.0,
   5.0, 6.0, 7.0, 8.0,
   9.0, 10.0, 11.0, 12.0,
  13.0, 14.0, 15.0, 16.0
};

static double B[SIZE/2][SIZE/2]; 

MPI_Datatype QUAD;
#define QUADRANT(Q,y,x) (Q[y * SIZE/2]+(x * SIZE/2))


void printout(double Y[SIZE/2][SIZE/2]){
    int i,j;
    for(i=0;i< SIZE/2;i++){
        for(j=0; j< SIZE/2; j++){
            printf("%.0f ",Y[i][j]);
        }
        printf("\n");
    }
}


int main(int argc, char** argv){
    int rank, size, i, j;

    MPI_Init(&argc,&argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    MPI_Comm_size(MPI_COMM_WORLD,&size);
    MPI_Status stat;

    //Define a MPI datatype, Quadrant
    MPI_Type_vector(SIZE/2, SIZE/2, SIZE, MPI_DOUBLE, &QUAD);
    MPI_Type_commit(&QUAD);

    //master process
    if(rank==0){
        MPI_Send(QUADRANT(A,0,1),1,QUAD,1,0, MPI_COMM_WORLD);
        MPI_Send(QUADRANT(A,1,0),1,QUAD,2,0,MPI_COMM_WORLD);
        MPI_Send(QUADRANT(A,1,1),1,QUAD,3,0,MPI_COMM_WORLD);

    }else{
         MPI_Recv(B,1,QUAD,0,0,MPI_COMM_WORLD,&stat);
         printout(B);
         printf("\n");
    }

    MPI_Finalize();
}

https://computing.llnl.gov/tutorials/mpi/samples/C/mpi_vector.c中有類似的程序

但是嘗試獲取列矩陣中的所有數字。

問題的大部分是您想要接收的不是QUAD ,而是直接的2x2子矩陣。 因此,代碼的發送部分很好。 但是,接收者是錯誤的。

因此,您需要進行修正的代碼是在發送側在發送之前將象限復制到直線2x2矩陣中,或者在接收方分配2x4接收緩沖區以存儲發送的消息,並復制相關的信息。然后分成2x2矩陣。

這是我選擇用於演示目的的第二個選項的代碼外觀,因為您似乎想使用派生類型。 (注:我保留了代碼樣式,盡管這不是我會自己使用的樣式)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<mpi.h>

//matrix size
#define SIZE 4

double A[SIZE][SIZE] ={
    1.0, 2.0, 3.0, 4.0,
    5.0, 6.0, 7.0, 8.0,
    9.0, 10.0, 11.0, 12.0,
    13.0, 14.0, 15.0, 16.0
};

static double B[SIZE/2][SIZE/2]; 
static double tmpB[SIZE/2][SIZE];

MPI_Datatype QUAD;
#define QUADRANT(Q,y,x) (Q[y * SIZE/2]+(x * SIZE/2))

void printout(double Y[SIZE/2][SIZE/2]){
    int i,j;
    for(i=0;i< SIZE/2;i++){
        for(j=0; j< SIZE/2; j++){
            printf("%.0f ",Y[i][j]);
        }
        printf("\n");
    }
}

void compress(double Y[SIZE/2][SIZE/2], double tmpY[SIZE/2][SIZE]){
    int i,j;
    for(i=0;i< SIZE/2;i++){
        for(j=0; j< SIZE/2; j++){
            Y[i][j]=tmpY[i][j];
        }
    }
}

int main(int argc, char** argv){
    int rank, size, i, j;

    MPI_Init(&argc,&argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    MPI_Comm_size(MPI_COMM_WORLD,&size);
    MPI_Status stat;

    //Define a MPI datatype, Quadrant
    MPI_Type_vector(SIZE/2, SIZE/2, SIZE, MPI_DOUBLE, &QUAD);
    MPI_Type_commit(&QUAD);

    //master process
    if(rank==0){
        MPI_Send(QUADRANT(A,0,1),1,QUAD,1,0,MPI_COMM_WORLD);
        MPI_Send(QUADRANT(A,1,0),1,QUAD,2,0,MPI_COMM_WORLD);
        MPI_Send(QUADRANT(A,1,1),1,QUAD,3,0,MPI_COMM_WORLD);

    }else{
        MPI_Recv(tmpB,1,QUAD,0,0,MPI_COMM_WORLD,&stat);
        compress(B,tmpB);
        printout(B);
        printf("\n");
    }

    MPI_Finalize();
}

最后一點:在現實生活中,如果您要進行此類傳輸,我建議您在發送數據之前尋求將數據壓縮到象限中的解決方案,以避免MPI庫本身內部出現額外的潛在無用的副本(盡管它們是否發生在MPI標准的范圍之外)

問題是, MPI_Recv與不符合接收緩沖區布局的跨步矢量數據類型一起使用。

例如,通話

MPI_Send(QUADRANT(A,0,1),1,QUAD,1,0, MPI_COMM_WORLD);

連同QUAD的定義一起,正確選擇A右上象限的數據值,並通過網絡發送值3.0、4.0、7.0和8.0。

但是,不能將相同的數據類型用於接收緩沖區,因為B中的行大小(因此跨度)比A小。 因此,值7.0和8.0存儲在B的邊界之外:

Matrix as seen by MPI_Recv     Memory Layout of
with data-type QUAD            Matrix B
M[0][0]      <-- 3.0 -->       B[0][0]
M[0][1]      <-- 4.0 -->       B[0][1]
M[0][2]                        B[1][0]    <-- unchanged, e.g. 0.0
M[0][3]                        B[1][1]    <-- unchanged, e.g. 0.0
M[1][0]      <-- 7.0 -->       !beyond array!
M[1][1]      <-- 8.0 -->       !beyond array!
M[1][2]
M[1][3]
...

編輯 :要符合標准,收到時必須使用相同的類型。 因此,必須這樣聲明接收緩沖區:

double B[SIZE/2][SIZE]; // SIZE elements per row.

然后,可以像Gilles在他的回答中所做的那樣壓縮數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM