Hi everyone,

I'm using the current Open MPI 1.8.1 release and observe
non-deterministic deadlocks and warnings from libevent when using
MPI_THREAD_MULTIPLE. Open MPI has been configured with
--enable-mpi-thread-multiple --with-tm --with-verbs (see attached
config.log)

Attached is a sample application that spawns a thread for each process
after MPI_Init_thread has been called. The thread then calls MPI_Recv
which blocks until the matching MPI_Send is called just before
MPI_Finalize is called in the main thread. (AFAIK MPICH uses such kind
of facility to implement a progress thread) Meanwhile the main thread
exchanges data with its right/left neighbor via ISend/IRecv.

I only see this, when the MPI processes run on separate nodes like in
the following:

$ mpiexec -n 2 -map-by node ./test
[0] isend/irecv.
[0] progress thread...
[0] waitall.
[warn] opal_libevent2021_event_base_loop: reentrant invocation. Only one event_base_loop can run on each event_base at once.
[1] isend/irecv.
[1] progress thread...
[1] waitall.
[warn] opal_libevent2021_event_base_loop: reentrant invocation. Only one event_base_loop can run on each event_base at once.

<no further output...>

Can anybody confirm this?

Best regards,
Markus

--
Markus Wittmann, HPC Services
Friedrich-Alexander-Universität Erlangen-Nürnberg
Regionales Rechenzentrum Erlangen (RRZE)
Martensstrasse 1, 91058 Erlangen, Germany
http://www.rrze.fau.de/hpc/

Attachment: info.tar.bz2
Description: Binary data

// Compile with: mpicc test.c -pthread -o test
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>


static void * ProgressThread(void * ptRank)
{
        int buffer = 0xCDEFCDEF;
        int rank = *((int *)ptRank);
        int error;

        printf("[%d] progress thread...\n", rank);
        MPI_Recv(&buffer, 1, MPI_INT, rank, 999, MPI_COMM_WORLD, 
MPI_STATUS_IGNORE);

        return NULL;
}


int main(int argc, char * argv[])
{
        int rank = -1;
        int size = -1;
        int bufferSend = 0;
        int bufferRecv = 0;
        int requested = MPI_THREAD_MULTIPLE;
        int provided = -1;
        int error;
        pthread_t thread;
        MPI_Request requests[2];

        MPI_Init_thread(&argc, &argv, requested, &provided);

        if (requested != provided) {
                printf("error: requested %d != provided %d\n", requested, 
provided);
                exit(1);
        }

        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
        MPI_Comm_size(MPI_COMM_WORLD, &size);

        error = pthread_create(&thread, NULL, &ProgressThread, &rank);

        if (error != 0) {
                fprintf(stderr, "pthread_create failed (%d): %s\n", error, 
strerror(error));
        }


        printf("[%d] isend/irecv.\n", rank);
        MPI_Isend(&bufferSend, 1, MPI_INT, (rank + 1) % size, 0, 
MPI_COMM_WORLD, &requests[0]);
        MPI_Irecv(&bufferRecv, 1, MPI_INT, (rank - 1 + size) % size, 0, 
MPI_COMM_WORLD, &requests[1]);

        printf("[%d] waitall.\n", rank);
        MPI_Waitall(2, requests, MPI_STATUS_IGNORE);

        printf("[%d] send.\n", rank);
        MPI_Send(&bufferSend, 1, MPI_INT, rank, 999, MPI_COMM_WORLD);

        error = pthread_join(thread, NULL);

        if (error != 0) {
                fprintf(stderr, "pthread_join failed (%d): %s\n", error, 
strerror(error));
        }

        printf("[%d] done.\n", rank);

        MPI_Finalize();

        return 0;
}

Reply via email to