Dips
Dips

Reputation: 11

MPI_send and MPI_receive function getting stuck

I have a code of page_rank where I have to compute page rank in parallel. My code hangs where I wrote the following MPI_send and MPI_receive function. What could be the problem?

int **sendto_list = (int **)malloc(comm_size*sizeof(int*));
for(i=0; i < comm_size; i++) {
    sendto_list[i] = (int *)malloc(18*sizeof(int));
    sendto_list[i][0] = 16;
    sendto_list[i][1] = 0;
}

int temp_data = 1;
for(i=0; i < comm_size; i++) {
    if(request_list[i][1] > 0) {
        for(k=0; k < request_list[i][1]; ) {
            for(j=0; j < 200; j++) {
                if( k >= request_list[i][1] )
                        break;

                sendrecv_buffer_int[j] = request_list[i][k+2];
                k++;
            }
            // Request appropriate process for pagerank.
            if(i!= my_rank)
                MPI_Send(&temp_data, 1, MPI_INT, i, TAG_PR_REQ, MPI_COMM_WORLD);
        }
    }

    if( i != my_rank )
        MPI_Send(&temp_data, 1, MPI_INT, i, TAG_PR_DONE, MPI_COMM_WORLD);
}

int expected_requests = 0, done = 0,temp,s;
s=0;
while( (done == 0) && (comm_size > 1) ) {
    if(expected_requests == (comm_size - 1))
        break;

    int count;
    // Receive pagerank requests or messages with TAG_PR_DONE(can be from any process).
    MPI_Recv(&temp, 1, MPI_INT, MPI_ANY_SOURCE ,MPI_ANY_TAG, MPI_COMM_WORLD, &status);

    MPI_Get_count(&status, MPI_INT, &count);

    switch(status.MPI_TAG) {
        case TAG_PR_REQ:{
            for(i = 0 ; i < count; i++)
                insert_into_adj_list(&sendto_list[status.MPI_SOURCE], sendrecv_buffer_int[i], num_nodes);
            break;
            }
            case TAG_PR_DONE:{
                expected_requests++;
                break;
            }
            default:
                break;
    }
}

Upvotes: 0

Views: 2229

Answers (1)

IKavanagh
IKavanagh

Reputation: 6187

A cursory glance over your code looks as if your issue is because your MPI_Send() calls are blocking and thus nothing is receiving and freeing them up.

If (request_list[i][1] > 0) and (i!= my_rank) evaluate to true you try to perform 2 MPI_Send() operations to process rank i but you only have 1 matching MPI_Recv() operation in each process, i.e. process rank i.

You may want to try changing

if(request_list[i][1] > 0) {
    ...
}

if( i != my_rank )
    MPI_Send(&temp_data, 1, MPI_INT, i, TAG_PR_DONE, MPI_COMM_WORLD);

to

if(request_list[i][1] > 0) {
    ...
} else if( i != my_rank ) {
    MPI_Send(&temp_data, 1, MPI_INT, i, TAG_PR_DONE, MPI_COMM_WORLD);
}

Note the addition of else turning if into else if. This ensures only 1 MPI_Send() operation per process. It does not look like the two MPI_Send() operations should be executed if the above conditions are true.


Alternatively if you need you could look into MPI_Isend() and MPI_Irecv(). Although I don't think they will solve your problem entirely in this case. I still think you need the else if clause.


I'd also like to point out in C there is no need to cast the return of malloc(). This topic has been covered extensively on StackOverflow so I won't dwell on it too long.

You should also check the result of malloc() is a valid pointer. It returns NULL if an error occured.

Upvotes: 2

Related Questions