smtnkc
smtnkc

Reputation: 508

Using Loops in MPI

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.

Upvotes: 2

Views: 8688

Answers (2)

Gilles
Gilles

Reputation: 9489

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;
}

Upvotes: 4

smtnkc
smtnkc

Reputation: 508

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.

Upvotes: 0

Related Questions