2

I am very new to MPI programing. In the following code, I am trying to add first 3 elements using process 1 and last 3 elements using process 2. Result should show Sum is 11 for the first three elements and Sum is 18 for the last three elements. I see the reason for my problem is that at rank 2 (process 2) it reads the arr[3] as the very first element of the array. I am really lost about why it doesn't read the 3rd element of the array correctly at rank 2

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

int main (int argc, char *argv[])
{
        MPI_Init(&argc, &argv);
        int world_rank;
        MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
        int world_size;
        MPI_Comm_size(MPI_COMM_WORLD, &world_size);
        int tag2 = 1;
        int tag1 = 2;       
        int arr[7] = { 6,2,3,9,4,5};

        printf ("\n--Current Rank: %d\n", world_rank);
        int index;
        int source = 0;
        int dest;
        if (world_rank == 0)
        {
            printf("* Rank 0 excecuting");
            index = 0;
            dest = 1;
            MPI_Send(&index, 1, MPI_INT, dest, tag1, MPI_COMM_WORLD);
            MPI_Send(&arr, 2, MPI_INT, dest, tag2, MPI_COMM_WORLD); 

            index = 3;
            dest = 2;
            MPI_Send(&index, 1, MPI_INT, dest, tag1, MPI_COMM_WORLD);
            MPI_Send(&arr, 1, MPI_INT, dest, tag2, MPI_COMM_WORLD);
        }
        else 
        {
            int sum = 0;
            int i;
            MPI_Recv(&index, 1, MPI_INT, source, tag1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            MPI_Recv(&arr[index], 20, MPI_INT, source, tag2, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            printf("At Rank: %d index is: %d\n", world_rank, index);
            for(i = index; i<=index+2; i++)
            {   
                printf("i: %d and arr[i]: %d\n", i, arr[i]);
                sum = arr[i]+sum;
            }
            printf("\n Sum is: %d and arr[3]: %d\n", sum, arr[3]);
        }       

        MPI_Finalize();
}

Result I get after using the command: mpirun -np 3 test1

--Current Rank: 0

--Current Rank: 1
At Rank: 1 index is: 0
i: 0 and arr[i]: 6
i: 1 and arr[i]: 2
i: 2 and arr[i]: 3

 Sum is: 11 and arr[3]: 9 //here it shows the correct value of 3rd array element

--Current Rank: 2
At Rank: 2 index is: 3
i: 3 and arr[i]: 6 //Error happens here
i: 4 and arr[i]: 4
i: 5 and arr[i]: 5

 Sum is: 15 and arr[3]: 6 //Show the wrong array value for 3rd element
* Rank 0 excecuting
D P.
  • 1,039
  • 7
  • 27
  • 56

2 Answers2

0

Hum, the code does what you told it to do...

        index = 3;
        dest = 2;
        MPI_Send(&index, 1, MPI_INT, dest, tag1, MPI_COMM_WORLD);
        MPI_Send(&arr, 1, MPI_INT, dest, tag2, MPI_COMM_WORLD);

Maybe you wanted more like:

        index = 3;
        dest = 2;
        MPI_Send(&index, 1, MPI_INT, dest, tag1, MPI_COMM_WORLD);
        MPI_Send(&arr[index], 3, MPI_INT, dest, tag2, MPI_COMM_WORLD);

And the fact that the other indexes were "valid" was because of the initial assignment...

There are also some more problems in this code:

  1. int arr[7] = { 6,2,3,9,4,5};: maybe rather int arr[] = {6,2,3,9,4,5};

  2. MPI_Send(&arr, 2, MPI_INT, dest, tag2, MPI_COMM_WORLD); should probably be MPI_Send(&arr[index], 3, MPI_INT, dest, tag2, MPI_COMM_WORLD); although I'm not too sure that is what you intended to do.

  3. MPI_Recv(&arr[index], 20, MPI_INT, source, tag2, MPI_COMM_WORLD, MPI_STATUS_IGNORE);: Where does this 20 come from? Shouldn't it be 3 rather?

Hope this makes sense to you.

Gilles
  • 9,269
  • 4
  • 34
  • 53
  • Thank you so much for explaining everything with examples and details. you are a big help – D P. Sep 13 '15 at 14:57
0

I am new to MPI. But this is what I know about MPI. Correct me if I am wrong.

  • Usually process with rank 0 receives messages from other processes and prints the results or it will do the necessary calculations(in this case add the two values that it receives)

  • All other processes do their part of work and sends it to process 0.

  • Tags are unnecessary in this case because this only involves simple calculations.

So the solution for this can be simplified like this.

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

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

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

        int arr[6] = {6,2,3,9,4,5};

        printf ("Current Rank: %d\n", world_rank);

        int total = 0;

        if(world_rank != 0){//if the rank is not 0, calculate the partial sum
            int tempTotal = 0;

            for(i = 0; i < 3; i++){
                tempTotal += arr[(world_rank -1)* 3 + i];
            }

            printf("* Rank %d sending value %d\n",world_rank, tempTotal);
            MPI_Send(&tempTotal, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);//send the partial sum to process 0
            printf("* Rank %d value sent\n", world_rank);

        }else{
            printf("RANK 0 receiving values:\n");

            int temp;

            for(i = 1; i < world_size; i++){
                MPI_Recv(&temp, 1, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);//receive partial sums from other processes

                printf("Received value %d from rank %d\n", temp, i);

                total += temp;//add the partial sum to total
            }

            printf("Sum of the array = %d\n", total);//after all partial sums arrive, print the total
        }       
        MPI_Finalize();
}

To run the code:

mpicc mpi.c -o mpi
mpirun -np 3 ./mpi

Hope this helps.

shan1024
  • 1,389
  • 7
  • 17
  • sorry but I tend to fully disagree with your view on the way MPI code usually work or should work... See my (lengthy I'm afraid) answer [here](http://stackoverflow.com/questions/32556639/how-to-call-same-rank-in-mpi-using-c-language/32558591#32558591) – Gilles Sep 15 '15 at 05:13
  • @Gilles: Thank you very much for sharing your experiences. I read your answer. It was really interesting. As I mentioned above, I am new to MPI. So if master/slaves approach is wrong, what kind of approach do you suggest for this kind of problem? – shan1024 Sep 15 '15 at 10:45
  • Which kind of problem? The kind of this specific question? Well actually, in real life, such a problem wouldn't occur, would it? But more generally, as explained on my post, most of the time, finding the right approach for addressing a parallel problem is to think globally, understanding what work needs to be done and by whom. And then making sure that (as much as possible), processes are able to acquire the data they need by themselves (with parallel IO possibly), do their work (in collaboration with the other processes) and issue their results in parallel, all being on an equal ground. – Gilles Sep 15 '15 at 10:57
  • I meant finding sum of an array using 2 processes kind of problem. What is your approach to solving this? – shan1024 Sep 15 '15 at 10:59
  • If the array isn't distributed already, there's no point in trying to parallelise the summation since transferring the data will take longer than doing it on the process which owns the data. If the array is already distributed, then each process does a partial reduction and then the global reduction is done using MPI_Reduce or MPI_Allreduce depending on where the result is needed. – Gilles Sep 15 '15 at 11:11
  • Thank you for your answer :) – shan1024 Sep 15 '15 at 13:36