2014-01-30 28 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。