2

I'm trying to sort large arrays by reversal and coding with MPI on C.

Basically, my program splits the array to portions for workers and each worker finds its own increasing and decreasing strips and sends strips back to root. Root makes some reversals by finding and using max and min elements of these strips. The program ends when there is no break point left, which means the array is sorted.

It was a very long code, so I simplified for my problem:

int *ARRAY;

int main(int argc, char *argv[]) 
{ 
    int p_id, n_procs, flag = 1;
    MPI_Init(&argc, &argv);
    MPI_Status status;
    MPI_Comm_rank(MPI_COMM_WORLD, &p_id);
    MPI_Comm_size(MPI_COMM_WORLD, &n_procs);

    if(p_id == 0) { 

        ARRAY = createRandomArray(N_DATA);
        // PRINT UNSORTED ARRAY

        while(hasBreakPoints(ARRAY, N_DATA)) {

            for(i=1;i<n_procs; i++) 
                // SEND PORTIONS TO WORKERS

            for(i=1;i<n_procs; i++)
                // RECEIVE EACH STRIP FROM WORKERS

            // FIND MAX AND MIN OF STRIPS
            // MAKE REVERSALS ON "ARRAY"    
        }
        flag = 0;
        // PRINT SORTED ARRAY
    }
    else {

        while(flag == 1) {
            // RECEIVE PORTION FROM ROOT
            // FIND MY OWN STRIPS
            // SEND MY OWN STRIPS TO ROOT
        }

    }
    MPI_Finalize();
    return 0;
}

As you can see, I need to use a while loop to run program until no break point left. I know that the number of MPI_Send commands have to be equal to the number of MPI_Receive commands. So, I simply created a flag to run ROOT and WORKERS equal times.

By use of this lazy approach, the program is working without error but never ending and doesn't goes into MPI_Finalize. Is there any fix on this or more efficient way to use? Thanks for help.

smtnkc
  • 488
  • 2
  • 9
  • 23
  • I found that workers run one more time than root. So, it is infinitely waiting at `MPI_Recv` statement. How can I solve it? – smtnkc Jan 17 '16 at 10:00
  • Your `flag` variable isn't shared across MPI processes... How do you expect the fact that process #0 changed its `flag` variable's value to be transmitted to the other processes? – Gilles Jan 17 '16 at 12:00
  • @Gilles oh, you are right. I missed that point. Sorry, I am new in parallel programming. How can I solve this problem? Thanks. – smtnkc Jan 17 '16 at 12:39

2 Answers2

4

Your flag variable being local to each process, you have to find a way of transferring its value from process #0 to the other processes when it changes.

Well actually, you can solve this issue by playing with message tags for example. Your worker processes could just just receive from root using MPI_ANY_TAG and decide what to do next, i.e sending back data or just finishing, depending on the actual tag value received. This could be look like this (not tested):

int *ARRAY;

int main(int argc, char *argv[]) 
{ 
    int p_id, n_procs, flag = 1;
    MPI_Init(&argc, &argv);
    MPI_Status status;
    MPI_Comm_rank(MPI_COMM_WORLD, &p_id);
    MPI_Comm_size(MPI_COMM_WORLD, &n_procs);

    const int COMPUTE=1, STOP=2;

    if(p_id == 0) { 

        ARRAY = createRandomArray(N_DATA);
        // PRINT UNSORTED ARRAY

        while(hasBreakPoints(ARRAY, N_DATA)) {

            for(i=1;i<n_procs; i++) 
                // SEND PORTIONS TO WORKERS using tag COMPUTE
                MPI_Send(......, COMPUTE, ...);

            for(i=1;i<n_procs; i++)
                // RECEIVE EACH STRIP FROM WORKERS

            // FIND MAX AND MIN OF STRIPS
            // MAKE REVERSALS ON "ARRAY"    
        }
        // send the STOP message using tag STOP
        for(i=1;i<n_procs; i++)
             MPI_Send(....,  STOP, ...);
        // PRINT SORTED ARRAY
    }
    else {

        while(flag == 1) {
            // RECEIVE PORTION FROM ROOT using MPI_ANY_TAG
            MPI_Recv(..., MPI_ANY_TAG, ..., &status);
            if ( status.MPI_TAG == COMPUTE ) {
                // FIND MY OWN STRIPS
                // SEND MY OWN STRIPS TO ROOT
            }
            else
                flag = 0;
        }

    }
    MPI_Finalize();
    return 0;
}
Gilles
  • 9,269
  • 4
  • 34
  • 53
  • Gilles, thank you! This is a really smart solution :) I wonder what kind of STOP message should I send? Normally I am sending whole array to workers with COMPUTE tag. At the end, should I send whole array again with STOP tag? I tried and this way worked but I think it is not good for performance? Thanks. – smtnkc Jan 18 '16 at 17:19
  • You don't have to send anything. You can just do `MPI_Send(NULL, 0, ..., STOP, ...);` and it doesn't matter about the rest. – Wesley Bland Jan 20 '16 at 01:15
0

As Gilles pointed out, flag can't be usable for my program. I solved the problem by checking that array is sorted or not in both ROOT's and WORKER's part. To do this, I have to pass ARRAY to workers from ROOT. And, optionally I keep ARRAY in worker part as LOCAL.

int *ARRAY;

int main(int argc, char *argv[]) 
{ 
    int p_id, n_procs;
    MPI_Init(&argc, &argv);
    MPI_Status status;
    MPI_Comm_rank(MPI_COMM_WORLD, &p_id);
    MPI_Comm_size(MPI_COMM_WORLD, &n_procs);

    if(p_id == 0) { 

        ARRAY = createRandomArray(N_DATA);
        // PRINT UNSORTED ARRAY

        while(hasBreakPoints(ARRAY, N_DATA)) {

                for(i=1;i<n_procs; i++) 
                // SEND WHOLE ARRAY TO ALL WORKERS

                for(i=1;i<n_procs; i++) 
                // SEND PORTIONS TO WORKERS

            for(i=1;i<n_procs; i++)
                // RECEIVE EACH STRIP FROM WORKERS

            // FIND MAX AND MIN OF STRIPS
            // MAKE REVERSALS ON "ARRAY"    
        }          
        // PRINT SORTED ARRAY
    }
    else {

        int *LOCAL;
        // RECEIVE ARRAY TO LOCAL

        while(hasBreakPoints(LOCAL, N_DATA) {
            // RECEIVE PORTION FROM ROOT
            // FIND MY OWN STRIPS
            // SEND MY OWN STRIPS TO ROOT
        }

    }
    MPI_Finalize();
    return 0;
}

Although I can't understand how, this solved my problem. I am still open for your opinions. Thanks.

smtnkc
  • 488
  • 2
  • 9
  • 23
  • I realized that receiving ARRAY only one time in WORKER site is not working in some cases. So, this is not an exact solution. I followed Gilles' method and solved the issue :) – smtnkc Jan 18 '16 at 17:21