2014-01-30 4 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_create является 0. Это флаг, указывающий, является ли оператор сокращения коммутативным. Матричное умножение не является коммутативным (но все же ассоциативным, как это требуется для всех операторов сокращения MPI), и поэтому здесь следует указать 0.

Смежные вопросы