2015-03-27 3 views
4

Я использую MPI_Probe для отправки сообщений динамически (где получатель не знает размер отправляемого сообщения). Мой код выглядит примерно так -Thread Safety с MPI_Probe

if (world_rank == 0) { 
    int *buffer = ... 
    int bufferSize = ... 
    MPI_Send(buffer, buffersize, MPI_INT, 1, 0, MPI_COMM_WORLD); 
} else if (world_rank == 1) { 
    MPI_Status status; 
    MPI_Probe(0, 0, MPI_COMM_WORLD, &status); 
    int count = -1; 
    MPI_Get_count(&status, MPI_INT, &count); 
    int* buffer = (int*)malloc(sizeof(int) * count); 
    MPI_Recv(buffer, count, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
} 

Если я бегу этот код в несколько потоков, есть шанс, что MPI_Probe вызывается в одном потоке и MPI_recv вызывается в другом потоке из планировщика перемежения нити , В сущности, приведенный выше код является безопасным для потоков.

+0

Вы совершенно правы, что это условие гонки, и не было никакого способа обойти это до MPI 3, с [MPI_Mprobe] (https://www.open-mpi.org/doc/v1.8/man3/MPI_Mprobe.3.php) и, возможно, MRecv , См. Например, сообщение в блоге Джеффа Сквайра (http://blogs.cisco.com/performance/mpi-forum-roundup). –

ответ

4

Прежде всего, MPI по умолчанию не является потокобезопасным. Вам нужно будет проверить, была ли ваша конкретная библиотека скомпилирована для обеспечения безопасности потоков, а затем инициализировать MPI, используя MPI_Init_thread вместо MPI_Init.

Предположим, что ваш экземпляр MPI инициализирован для потокобезопасных процедур, ваш код по-прежнему не является потокобезопасным из-за состояния гонки, которое вы уже идентифицировали.

Спаривание MPI_Probe и MPI_Recv в многопоточной среде не поточно, это известная проблема в MPI-2: http://htor.inf.ethz.ch/publications/img/gregor-any_size-mpi3.pdf

Есть по крайней мере два возможных решения. Вы можете использовать MPI-3 MPI_Mprobe и MPI_MRecv или использовать блокировку/мьютекс вокруг критического кода. Это может выглядеть следующим образом:

MPI-2 раствор (с использованием мьютекса/блокировки):

int number_amount; 
if (world_rank == 0) { 
    int *buffer = ... 
    int bufferSize = ... 
    MPI_Send(buffer, buffersize, MPI_INT, 1, 0, MPI_COMM_WORLD); 
} else if (world_rank == 1) { 
    MPI_Status status; 
    int count = -1; 
    /* aquire mutex/lock */ 
    MPI_Probe(0, 0, MPI_COMM_WORLD, &status); 
    MPI_Get_count(&status, MPI_INT, &count); 
    int* buffer = (int*)malloc(sizeof(int) * count); 
    MPI_Recv(buffer, count, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
    /* release mutex/lock */ 
} 

MPI-3 решение:

int number_amount; 
if (world_rank == 0) { 
    int *buffer = ... 
    int bufferSize = ... 
    MPI_Send(buffer, buffersize, MPI_INT, 1, 0, MPI_COMM_WORLD); 
} else if (world_rank == 1) { 
    MPI_Status status; 
    MPI_Message msg; 
    int count = -1; 
    MPI_Mprobe(0, 0, MPI_COMM_WORLD, &msg, &status); 
    MPI_Get_count(&status, MPI_INT, &count); 
    int* buffer = (int*)malloc(sizeof(int) * count); 
    MPI_Mrecv(buffer, count, MPI_INT, &msg, MPI_STATUS_IGNORE); 
}