Stranko
Stranko

Reputation: 165

MPI joining vectors

I'm trying to do some parallel calculations and then reduce them to one vector.

I try it by dividing for loop into parts which should be calculated separatedly from vector. Later I'd like to join all those subvectors into one main vector by replacing parts of it with values gotten from processes. Needless to say, I have no idea how to do it and my tries were in vain.

Any help will be appreciated.

MPI_Barrier(MPI_COMM_WORLD);
MPI_Bcast(A, n*n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Bcast(b, n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Bcast(x0, n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
printf("My id: %d, mySize: %d, myStart: %d, myEnd: %d", rank, size, mystart, myend);
while(delta > granica)
{
    ii++;
    delta = 0;
    //if(rank > 0)
    //{
        for(i = mystart; i < myend; i++)
        {
            xNowe[i] = b[i];
            for(j = 0; j < n; j++)
            {
                if(i != j)
                {
                    xNowe[i] -= A[i][j] * x0[j];
                }
            }
            xNowe[i] = xNowe[i] / A[i][i];
            printf("Result in iteration %d: %d", i, xNowe[i]);
        }
        MPI_Reduce(xNowe, xNowe,n,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);

Upvotes: 2

Views: 663

Answers (1)

Wesley Bland
Wesley Bland

Reputation: 9072

I'm going to ignore your calculations and assume they're all doing whatever it is you want them to do and at the end, you have an array called xNowe that has the results for your rank somewhere within it (in some subarray).

You have two options.

The first way uses an MPI_REDUCE in the way you're currently doing it.

What needs to happen is that you should probably set all of the values that do not pertain to your rank to 0, then you can just do a big MPI_REDUCE (as you're already doing), where each process contributes its xNowe array which will look something like this (depending on the input/rank/etc.):

rank:    0   1   2   3   4   5   6   7
value:   0   0   1   2   0   0   0   0

When you do the reduction (with MPI_SUM as the op), you'll get an array (on rank 0) that has each value filled in with the value contributed by each rank.

The second way uses an MPI_GATHER. Some might consider this to be the "more proper" way.

For this version, instead of using MPI_REDUCE to get the result, you only send the data that was calculated on your rank. You wouldn't have one large array. So your code would look something like this:

MPI_Barrier(MPI_COMM_WORLD);
MPI_Bcast(A, n*n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Bcast(b, n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Bcast(x0, n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
printf("My id: %d, mySize: %d, myStart: %d, myEnd: %d", rank, size, mystart, myend);
while(delta > granica)
{
    ii++;
    delta = 0;

    for(i = mystart; i < myend; i++)
    {
        xNowe[i-mystart] = b[i];
        for(j = 0; j < n; j++)
        {
            if(i != j)
            {
                xNowe[i] -= A[i][j] * x0[j];
            }
        }
        xNowe[i-mystart] = xNowe[i-mystart] / A[i][i];
        printf("Result in iteration %d: %d", i, xNowe[i-mystart]);
    }
}
MPI_Gather(xNowe, myend-mystart, MPI_DOUBLE, result, n, MPI_DOUBLE, 0, MPI_COMM_WORLD);

You would obviously need to create a new array on rank 0 that is called result to hold the resulting values.

UPDATE:

As pointed out by Hristo in the comments below, MPI_GATHER might not work here if myend - mystart is not the same on all ranks. If that's the case, you'd need to use MPI_GATHERV which allows you to specify a different size for each rank.

Upvotes: 2

Related Questions