Search code examples
c++performanceparallel-processingmpihpc

Why is my MPI parallel program printing twice?


My program is sorting array and works fine but I have only one small problem, it prints the unsorted array more then 1 time( depending on how much processes I have selected, if I select 2 it prints twice ). I just want to print the unsorted array only once. Is there a way of doing this? Thanks for your help :).

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

void merge(int*, int*, int, int, int);
void mergeSort(int*, int*, int, int);

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

    /********** Create and populate the array **********/
    int n = atoi(argv[1]);
    int* original_array{ new int[n] {} };
    //int original_array[]=new int[n];

    int c;
    srand(time(NULL));
    printf("This is the unsorted array: ");
    for (c = 0; c < n; c++) {
        original_array[c] = rand() % n;
        printf("%d ", original_array[c]);
    }

    printf("\n");
    printf("\n");

    /********** Initialize MPI **********/
    int world_rank;
    int world_size;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);

    /********** Divide the array in equal-sized chunks **********/
    int size = n / world_size;

    /********** Send each subarray to each process **********/
    int* sub_array{ new int[size] {} };
    MPI_Scatter(original_array, size, MPI_INT, sub_array, size, MPI_INT, 0, MPI_COMM_WORLD);

    /********** Perform the mergesort on each process **********/
    int* tmp_array{ new int[size] {} };
    mergeSort(sub_array, tmp_array, 0, (size - 1));

    /********** Gather the sorted subarrays into one **********/
    int* sorted = NULL;
    if (world_rank == 0) {
        sorted={ new int[n] {} } ;
    }


    MPI_Gather(sub_array, size, MPI_INT, sorted, size, MPI_INT, 0, MPI_COMM_WORLD);

    
    /********** Povik na posledniot mergeSort call **********/
    if (world_rank == 0) {

        printf("Array state before final mergeSort call: ");
        for (c = 0; c < n; c++) {
            printf("%d ", sorted[c]);
        }
        
        printf("\n");

        int* other_array{ new int[n] {} };
        mergeSort(sorted, other_array, 0, (n - 1));

        /********** Pecati sortirana niza **********/
        printf("This is the sorted array: ");
        for (c = 0; c < n; c++) {
            printf("%d ", sorted[c]);
        }

        printf("\n");
        printf("\n");

        /********** Oslobodi memorija **********/
        delete[] sorted;
        delete[] other_array;

    }

    /********** Oslobodi memorija **********/
    delete[] original_array;
    delete[] sub_array;
    delete[] tmp_array;

    /********** Finalize MPI **********/
    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Finalize();

}

Solution

  • You need to move this:

       printf("This is the unsorted array: ");
        for (c = 0; c < n; c++) {
    
            original_array[c] = rand() % n;
            printf("%d ", original_array[c]);
    
        }
    

    below the

    int world_rank;
    int world_size;
    
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);
    

    and make only one process to print it, for instance, using rank = 0.

    For instance:

      if(rank == 0){
        printf("This is the unsorted array: ");
        for (c = 0; c < n; c++) {
    
            original_array[c] = rand() % n;
            printf("%d ", original_array[c]);
    
        }
     }
    

    What is happen is that your MPI implementation is spawning as many instance of that code as the number of processes that you have specified right from the beginning of that code and not from the MPI_Init call onwards. You can read in more detail explanation about this here.

    MPI is a multi-process paradigm and typically all processes are started together and execute exactly the same code before MPI_Init().

    With this in mind you might have to adapt the rest of code accordingly. That last MPI_Barrier(MPI_COMM_WORLD); looks redundant.