Собственная реализация умножения матриц с MPI Send / Recv - PullRequest
0 голосов
/ 19 сентября 2019

Я попытался написать функцию с именем matrixMultiply , которая просто берет две матрицы 4 x 4, называемые a и b, умножает их и сохраняет результат в матрице 4 x 4 c.После этого я хотел расширить программу на более общую для nxn матриц.К сожалению, программа компилируется, но застревает при ее выполнении.Я был бы очень благодарен за то, что кто-то из вас смог сказать мне, где моя ошибка.

#import <stdio.h>
#import "mpi.h"

void matrixMultiply(int argc, char* argv[], int a[][4], int b[][4], int c[][4])
{
    int n = 4;
    int procs;
    int rank;
    int rootRank = 0;

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

    if(rank == rootRank) {
        int current_row[4];
        for(int i = 0; i < n; i++) {

            int current_column[4];
            for(int j = 0; j < n; j++) {

                //getting the i-th row
                for(int k = 0; k < n; k++) {
                    current_row[k] = a[i][k];
                }

                //getting the j-th column
                for (int k = 0; k < n; k++)
                {
                    current_column[k] = b[k][j];
                }

                //MPI_Send(void* data, int count, MPI_Datatype datatype, int destination, int tag, MPI_Comm communicator)
                MPI_Bsend(current_row, 4, MPI_INT, i, 0, MPI_COMM_WORLD);
                MPI_Bsend(current_column, 4, MPI_INT, i, 1, MPI_COMM_WORLD);

                int result;
                //MPI_Recv(void* data, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm communicator, MPI_Status* status)
                MPI_Recv(&result, 1, MPI_INT, i ,2, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
                c[i][j]=result;
            }
        }

        /* this code is only used to check the resulting matrix c*/
        printf("c:\n");
        for(int i = 0; i < 4; i++) {
            for(int j = 0; j < 4; j++) {
                printf("%d ", c[i][j]);
            }
            printf("\n");
        }
        printf("\n");

    }
    else {
        int result = 0;
        int local_row[4] = {0,0,0,0};
        int local_column[4] = {2,2,2,2};

        //MPI_Recv(void* data, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm communicator, MPI_Status* status)
        MPI_Recv(local_row, 4, MPI_INT, rootRank, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        MPI_Recv(local_column, 4, MPI_INT, rootRank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

        for(int i = 0; i < 4; i++) {
            result+= local_row[i] * local_column[i];
        }

        //MPI_Send(void* data, int count, MPI_Datatype datatype, int destination, int tag, MPI_Comm communicator)
        MPI_Bsend(&result, 1, MPI_INT, rootRank, 2, MPI_COMM_WORLD);
    }
    MPI_Finalize();
    return;
}

int main(int argc, char* argv[]) {
    int d[][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12},{13,14,15,16}};
    int e[][4] = {{16,15,14,13}, {12,11,10,9}, {8,7,6,5}, {4,3,2,1}};
    int f[][4] = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}};

    matrixMultiply(argc, argv, d, e, f);

}

1 Ответ

0 голосов
/ 25 сентября 2019

Пара вопросов по адресу:

MPI_Bsend (в отличие от MPI_Send) требуется предшествующий вызов MPI_Buffer_attach.См. Примечания здесь: https://www.mpich.org/static/docs/latest/www3/MPI_Bsend.html или любая последняя версия спецификации MPI.

Сначала попробуйте с этим изменением.Возможно, этого достаточно, чтобы все заработало.Если нет, дважды проверьте любой порядок отправки и получения, рассматриваемый глобально, чтобы увидеть, есть ли в системе тупик.

Кроме того, вы можете улучшить производительность, а также избежать некоторых сценариев взаимоблокировки.переключаясь на неблокирующие отправления и получения (MPI_Isend, MPI_Irecv и связанные с ними) и завершая их через MPI_Waitall, MPI_Testall или аналогичные после того, как все они были инициированы.Это было бы больше похоже на то, как реализации MPI обычно выполняют коллективные операции под капотом - что также может иметь преимущества в производительности по сравнению с отдельными вызовами отправки и получения, поскольку реализация знает больше об аппаратном обеспечении и о том, что происходит под капотом, и можетоптимизировать порядок вокруг этого.То, что вы делаете, выглядит как MPI_Bcast, за которым следует MPI_Gather, как один из возможных альтернативных шаблонов, который будет в большей степени опираться на реализацию, чтобы позаботиться об оптимизации для вас.

...