MPI: разделение строки на несколько процессов - PullRequest
0 голосов
/ 05 июля 2018

Я пытаюсь разбить матрицу (массив) на несколько процессов. Мой код основан на:

Использование ScatterV для разделения массива на несколько процессов

Мне нужно сделать это динамически. Когда я присваиваю значения sendcounts и displs статически работает нормально, но если я это сделаю, использование цикла завершится неудачно. Показывать только первые 5 элементов. Я не думаю, что это связано с MPI, но я не смогу заставить его работать.

Это код:

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

#define ROOT 0
#define N 5



/** 
 * 
 * With this row
 * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 
 *
 * Assign portions to each process.
 * 
 * Execution with 3 process
 * 
 * From  0 to 4  assigned to process  0
 * From  5 to 9  assigned to process  1
 * From  10 to 24  assigned to process  2
 */




int *createMatrix(int nRows, int nCols) {

  int *matrix;

  int h, i, j;

  if ((matrix = malloc(nRows * nCols * sizeof(int))) == NULL) {
    printf("Malloc error:");
    exit(1);
  }

  //Test values 
  for (h = 0; h < nRows * nCols; h++) {
    matrix[h] = h;
  }

  return matrix;
}


void printArray(int *row, int nElements) {

    int i;
    for (int i = 0; i < nElements; i++) {
        printf("%d ", row[i]);
    }
    printf("\n");
}




int main(int argc, char **argv) {

    // for storing this process' rank, and the number of processes
    int rank, np;  

    int i, j;

    int begin, end;
    int *matrix;



    int *sendcounts, *displs, *recvbuf;  


    MPI_Status status;

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


    //Initialize matrix 
    if (rank == ROOT) {
        matrix = createMatrix(N, N);
        printf("Initial matrix: \n");
        printArray(matrix, N*N);    
    }



    int lastRow;
    int quotient = N / np;
    int multiplicacion = quotient * np;
    if (multiplicacion < N) {
        lastRow = quotient + (N - (quotient * np));
    } else {
        lastRow = quotient;
    }

    printf("PROCESS: %d\n", rank);
    printf("quotient: %d\n", quotient);
    begin = rank * quotient;
    if (rank == np -1) {
        end = N - 1;
    }else if (rank == ROOT) { 
        end = begin + quotient - 1 ;
    }else {
        end = (quotient * rank + quotient) - 1;
    }

    printf("begin: %d\n", begin);
    printf("end: %d\n", end);
    printf("total elements: %d\n", end - begin + 1);


    //scatterv SECTION
    //array with number of elements per process
    sendcounts = malloc(np * sizeof(int));
    //array with the initial address in the main vector (matrix)
    displs = malloc(np * sizeof(int));




    printf("Process %d, begin: %d\n", begin, rank);

    //Using this option WORKS correct
    sendcounts[0] = 5;
    sendcounts[1] = 5;
    sendcounts[2] = 15;
    displs[0] = 0;
    displs[1] = 5;
    displs[2] = 10;

    //Using this loop FAILS, assign the first 5 elements
    //for (i = 0; i < np; i++){
    //  sendcounts[i] = (end - begin + 1) * 5;
    //  displs[i] = begin * N;
    //}


    printf("sendcounts[%d]: %d\n", rank, sendcounts[rank]);
    printf("displs[%d]: %d\n", rank, displs[rank]);


    recvbuf = malloc(sendcounts[rank] * sizeof(int));


    for (i = 0; i < sendcounts[rank]; i++) {
        recvbuf[i] = 0;
    }

    MPI_Scatterv(matrix, sendcounts, displs, MPI_INT, recvbuf, sendcounts[rank], MPI_INT, ROOT, MPI_COMM_WORLD);



    printArray(recvbuf, sendcounts[rank]);
    printf("\n");

    free(recvbuf);
    recvbuf=NULL;

    MPI_Finalize();
    return 0;
}

Любая идея, почему, если я использую этот код, он терпит неудачу:

 for (i = 0; i < np; i++){
        sendcounts[i] = (end - begin + 1) * 5;
        displs[i] = begin * N;
   }

спасибо

Desired output:
Initial matrix: 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 

PROCESS: 0
sendcounts[0]: 5
displs[0]: 0
0 1 2 3 4 

PROCESS: 1
sendcounts[1]: 5
displs[1]: 5
5 6 7 8 9 

PROCESS: 2
sendcounts[2]: 15
displs[2]: 10
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 

ОБНОВЛЕНИЕ 1:

Я изменил код, чтобы включить инициализацию sendcounts и displs в ROOT, но проблема в том, что я теряю значения размеров recvbuf и размера recvbuf для каждого процесса.

int main(int argc, char **argv) {

    // for storing this process' rank, and the number of processes
    int rank, np;  

    int i, j;

    int begin, end;
    int *matrix;



    int *sendcounts, *displs, *recvbuf;  


    MPI_Status status;

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


    sendcounts = malloc(np * sizeof(int));
    //array with the initial address in the main vector (matrix)
    displs = malloc(np * sizeof(int));

    //Initialize matrix 
    if (rank == ROOT) {
        matrix = createMatrix(N, N);
        printf("Initial matrix: \n");
        printArray(matrix, N*N);    


        int lastRow;
        int quotient = N / np;
        int multiplicacion = quotient * np;
        if (multiplicacion < N) {
            lastRow = quotient + (N - (quotient * np));
        } else {
            lastRow = quotient;
        }
        for (i = 0; i < np; i++) {
            begin = i * quotient;
            if (i == np -1) {
                end = N - 1;
            }else if (i == ROOT) { 
                end = begin + quotient - 1 ;
            }else {
                end = (quotient * i + quotient) - 1;
            }

            sendcounts[i] = (end - begin + 1) * N;
            displs[i] = begin * N;
            printf("assigning sendcounts[%d]: %d\n", i, sendcounts[i]);
            printf("assigning displs[%d]: %d\n", i, displs[i]);

            recvbuf = malloc(sendcounts[rank] * sizeof(int));

        }
    }


    printf("sendcounts[%d]: %d\n", rank, sendcounts[rank]);
    printf("displs[%d]: %d\n", rank, displs[rank]);


    //  recvbuf = malloc(sendcounts[rank] * sizeof(int));
    //sendcounts outside ROOT doesn't exit

    MPI_Scatterv(matrix, sendcounts, displs, MPI_INT, recvbuf, sendcounts[rank], MPI_INT, ROOT, MPI_COMM_WORLD);



    printArray(recvbuf, sendcounts[rank]);
    printf("\n");

    free(recvbuf);
    recvbuf=NULL;

    MPI_Finalize();
    return 0;
}
...