Search code examples
arrayscparallel-processingmpifactorial

How to send an integer array Using MPI and calculate factorial of them?


Consider that process 0 have an array of integer numbers where we should compute the factorial of all the elements in the array. Modify the program in order to send the array to process 1 that computes all the factorials and return the results to process 0.

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <mpi.h>
    int main (int argc, char ** argv)
    {
        int rank, size,code,tag=100;
        int a[10]={1,2,3,4,5,6,7,8,9,10};
        int count,fact = 1,i,j,k;
        MPI_Init (&argc, &argv);    /* starts MPI */
        MPI_Comm_rank (MPI_COMM_WORLD, &rank);  /* get current process id */
      
        if (rank == 0) {
           for ( i = 0; i < 9; ++i)
           {
              code=MPI_Send(&a[i],1, MPI_INTEGER,1,tag, MPI_COMM_WORLD);
              code=MPI_Recv(&fact,1, MPI_INTEGER,1,tag, MPI_COMM_WORLD,MPI_STATUSES_IGNORE);
               printf("Process %d,Result=%d\n",rank,fact);
           }
        } 
       else if (rank == 1) 
       {
          for (int j = 0; j < 9; ++j)
          {
             code=MPI_Recv(&a[j],1, MPI_INTEGER,0,tag, MPI_COMM_WORLD,MPI_STATUSES_IGNORE);
             count = j;
             for ( k = 0; k < count; ++k)
             {
                  fact = fact*(j+1);
                  code=MPI_Send(&fact,1, MPI_INTEGER,0,tag, MPI_COMM_WORLD);
             }
        }  
     }
      
    
      MPI_Comm_size (MPI_COMM_WORLD, &size);    /* get number of processes */
     
      MPI_Finalize();
     
     
      return 0;
    }

Solution

  • There are some issues with your code, namely MPI_INTEGER is not a valid MPI C data type (albeit it is valid in MPI fortran), MPI_INT is. Moreover, the way you are calculating the factorial is assuming that the elements coming from process 0 will always be continuous natural numbers from 1 to N. You should not assume that, and you do not need to send each element separately, rather do the following:

    Process 0:

    1. create the array with the values to calculate the factorial of it;
    2. create an array to store the factorials that will be send by process 1;
    3. send the entire array (created in 1.) to process 1;
    4. wait (i.e., calling MPI_recv) for the results that will come from process 1.

    Process 1:

    1. create an array to store the values that will be send by process 0;
    2. wait for (i.e., calling MPI_recv) the values coming from process 0;
    3. create an array to store the factorials;
    4. calculate the factorials;
    5. store them in the array created for that purpose;
    6. send the array with the factorials to the process 0.

    The code would look like:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <mpi.h>
    int main (int argc, char ** argv){
        int rank, size,tag=100;
        MPI_Init (&argc, &argv);  /* starts MPI */
        MPI_Comm_rank (MPI_COMM_WORLD, &rank);    /* get current process id */
      
        if (rank == 0)
        {
            int a[10]={1,2,3,4,5,6,7,8,9,10}; // the array with the values to calculate the factorial
            int fact[10] = {0}; // the array to store the results
            MPI_Send(a, 10, MPI_INT,1,tag, MPI_COMM_WORLD); // the values 
            MPI_Recv(fact, 10, MPI_INT,1,tag, MPI_COMM_WORLD,MPI_STATUSES_IGNORE); // wait for the result 
            for(int i = 0; i < 10; i++) // print the results;
               printf("Process %d,Result=%d\n",rank, fact[i]);
        } 
        else if (rank == 1) 
        { 
           int a[10] = {0};
           int fact[10] = {0};
           MPI_Recv(a, 10, MPI_INT,0,tag, MPI_COMM_WORLD,MPI_STATUSES_IGNORE);
           for(int i = 0; i < 10; i++){
               int f = 1;
               for (int k = 1; k <= a[i]; ++k) // Calculate the factorials 
                    f *= k; 
               fact[i] = f;
           }
           MPI_Send(fact,10, MPI_INT,0,tag, MPI_COMM_WORLD); // send the factorials to process 0
        }
        MPI_Comm_size (MPI_COMM_WORLD, &size);    /* get number of processes */
        MPI_Finalize();
        return 0;
    }
    

    INPUT : {1,2,3,4,5,6,7,8,9,10}

    OUTPUT

    Process 0,Result=1
    Process 0,Result=2
    Process 0,Result=6
    Process 0,Result=24
    Process 0,Result=120
    Process 0,Result=720
    Process 0,Result=5040
    Process 0,Result=40320
    Process 0,Result=362880
    Process 0,Result=3628800