2014-01-30 31 views
0

例如,如果我要乘4的2倍2的矩陣一起,爲簡單起見,假設所有的人都是相同的,並且有條目1.矩陣乘法和全球減少操作MPI

然後我想知道我應該如何使用mpi的全球減排來實現這一目標?我們假設大小爲4.

您能否給我一個這樣做的想法?謝謝!

# include <stdio.h> 
# include <mpi.h> 
# define N 4 

//Create the 2 times 2 matrix type 
typedef double Matrix[2][2]; 

void printMatrix(Matrix m); 
void unitMatrix(Matrix m); 
void randomMatrix(Matrix m); 
void multMatrix(Matrix r, Matrix a, Matrix b); 
void copyMatrix(Matrix out, Matrix in); 
double random_number(void); 
void my_range(int n, int *i1, int *i2); 

int main(int argc, char *argv[]) 
{ 
    //Create a single matrix a 
    Matrix a; 
    Matrix buf; 
    //Create a set of 100 matrix 
    Matrix b[N]; 
    int i; 
    int rank, i1, i2; 
    double row1[2]; 
    double row2[2]; 
    double col1[2]; 
    double col2[2]; 


    MPI_Init(&argc, &argv); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    my_range(N, &i1, &i2); 

    for (i = 0; i < i1; i++) { 
     randomMatrix(a); 
    } 
    for (i = i1; i <= i2; i++) { 
    randomMatrix(b[i]); 
    } 
    for (i = i2 + 1; i < N; i++) { 
     randomMatrix(a); 
    } 

    unitMatrix(a); 

    for (i = i1; i <= i2; i++) { 
    multMatrix(a, a, b[i]); 
    MPI_Reduce(&a,&buf, 4, MPI_DOUBLE, MPI_PROD, 0, 
      MPI_COMM_WORLD); 
    } 

    if (rank == 0) printMatrix(buf); 

    MPI_Finalize(); 
    return 0; 
} 

//print a single matrix 
void printMatrix(Matrix m) 
{ 
    printf("%26.18e %26.18e %26.18e %26.18e\n", 
     m[0][0], m[0][1], m[1][0], m[1][1]); 
} 

void unitMatrix(Matrix m) 
{ 
    m[0][0] = 1.0; 
    m[0][1] = 0.0; 
    m[1][0] = 0.0; 
    m[1][1] = 1.0; 
} 

void randomMatrix(Matrix m) 
{ 
    m[0][0] = 1.0; 
    m[0][1] = 1.0; 
    m[1][0] = 1.0; 
    m[1][1] = 1.0; 
} 

double random_number(void) 
{ 
    const int mr = 714025; 
    const int ia = 1366; 
    const int ic = 150889; 
    const double qdnorm = 1.0/mr; 
    static int irandom = 0; 

    irandom = (ia * irandom + ic) % mr; 
    return(irandom * qdnorm); 
} 

void multMatrix(Matrix r, Matrix a, Matrix b) 
{ 
    // multMatrix(r, a, b) calculates r = a * b 
    // multMatrix(a, a, b) calculates a = a * b 
    // multMatrix(a, b, a) calculates a = b * a 

    Matrix tmp; 

    tmp[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1]; 
    tmp[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1]; 
    tmp[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1]; 
    tmp[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1]; 

    copyMatrix(r, tmp); 
} 

void copyMatrix(Matrix out, Matrix in) 
{ 
    out[0][0] = in[0][0]; 
    out[0][1] = in[0][1]; 
    out[1][0] = in[1][0]; 
    out[1][1] = in[1][1]; 
} 

void my_range(int n, int *i1, int*i2) 
{ 
    int size, rank, chunk, rest; 

    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    chunk = n/size; 
    rest = n % size; 

    if (rank < rest) { 
    chunk = chunk + 1; 
    *i1 = chunk * rank; 
    } else { 
    *i1 = chunk * rank + rest; 
    } 

    *i2 = *i1 + chunk - 1; 
} 
+3

有很多關於如何使用MPI將兩個矩陣相乘的工作,您能告訴我們您嘗試了什麼,以及爲什麼它沒有工作,我們可以嘗試幫助您?我們並沒有真正爲這裏的人做家庭作業問題,直到他們表明他們也完成了自己的工作。 –

+0

我不是問如何並行化矩陣乘法本身,而是矩陣鏈的並行化。假設矩陣通常與對方相乘。如你所知,矩陣乘法是關聯的,但不是可交換的。所以,如果我們有100個矩陣,那麼我們絕對可以使4個線程同時處理25個矩陣乘法,然後使用全局約簡來結合局部結果。現在我被困在如何結合這些本地結果。 – Cancan

+0

我試着直接減少產品,但沒有成功。 – Cancan

回答

2

您的代碼使用基於元素的矩陣乘法來減少部分結果,即r[i][j] = a[i][j] * b[i][j],因此會給出錯誤結果。正如haraldkl所指出的那樣,您可以使用MPI的機制來爲用戶定義的MPI減少運算符MPI_Op_create。您還應該創建用戶定義的MPI數據類型,以便能夠將每個陣列作爲單個矩陣實體處理。例如:

void myMatrixProd(Matrix *in, Matrix *inout, int *len, MPI_Datatype *dptr) 
{ 
    int i; 

    for (i = 0; i < *len; i++) 
    { 
     multMatrix(inout[i], in[i], inout[i]); 
    } 
} 

... 

MPI_Op multOp; 
MPI_Datatype matrixType; 

MPI_Type_contiguous(2*2, MPI_DOUBLE, &matrixType); 
MPI_Type_commit(&matrixType); 

MPI_Op_create(myMatrixProd, 0, &multOp); 

Matrix a, buf; 

// Compute partial product into a 
multMatrix(...); 

// Reduce the partial products to get the total into rank 0 
MPI_Reduce(&a, &buf, 1, matrixType, multOp, 0, MPI_COMM_WORLD); 

要注意的重要一點是,第二個參數是MPI_Op_create0。這是一個標誌,表明歸約操作符是否可交換。矩陣乘法不是可交換的(但仍然是所有MPI簡化算子所需的關聯),因此應該在那裏指定0。