Правильное использование MPI_THREAD_SERIALIZED с pthreads - PullRequest
2 голосов
/ 28 апреля 2011

После прочтения некоторых спецификаций MPI я понял, что при инициализации с помощью MPI_THREAD_SERIALIZED программа должна гарантировать, что вызовы MPI_Send / Recv, которые происходят в отдельных потоках, не должны перекрываться. Другими словами, вам нужен мьютекс для защиты вызовов MPI.

Рассмотрим эту ситуацию:

Mutex mpi_lock = MUTEX_INITIALIZER;

void thread1_function(){
    while(true){
        /* things happen */

        lock(mpi_lock);
        MPI_Send(/* some message */);
        unlock(mpi_lock);

        /* eventually break out of loop */
    }
}

void thread2_function(){
    while(true){
        /* things happen */

        char *buffer = CREATE_BUFFER();
        lock(mpi_lock);
        MPI_Recv(buffer /* some message stored in buffer */);
        unlock(mpi_lock);

        /* eventually break out of loop */
    }
}

int main(){
    create_thread(thread1_function);
    create_thread(thread2_function);

    return 0;
}

Вот мой вопрос: это правильный метод и / или это необходимо? В моей ситуации я должен предположить, что могут быть большие промежутки времени между сообщениями, полученными в thread2_function (). Есть ли способ не допустить, чтобы thread1_function () пришлось ждать, пока thread2_function () завершит получение, прежде чем сможет выполнить отправку?

Я уже знаю о MPI_THREAD_MULTIPLE, но системные ограничения означают, что это недоступно для меня.

Я открыт для предложений по реструктуризации кода, но моя цель - создать «основной» поток, который постоянно работает и результаты MPI_Send без прерывания, в то время как другой поток управляет получением и добавлением в очередь для основного потока.

Заранее спасибо.

1 Ответ

2 голосов
/ 08 августа 2011

Такая внешняя блокировка (или другая аналогичная схема синхронизации) крайне необходима, когда используется только MPI_THREAD_SERIALIZED.Единственный способ обойти это - использовать MPI_THREAD_MULTIPLE, но это кажется вам недоступным.Также, пожалуйста, не пытайтесь использовать MPI_THREAD_SINGLE или MPI_THREAD_FUNNELED вместо SERIALIZED в этой ситуации, есть некоторые платформы и реализации, где это приведет к поломке небольших частей MPI.

Код, который вы разместили выше, может иметь проблемы, если вы отправляете / получаете сообщения между потоками внутри процесса.Если thread2 запущен, получает блокировку и вводит MPI_Recv до того, как thread1 сможет получить блокировку и отправить сообщение на thread2 через MPI_Send, тогда будет тупик, потому что thread1 никогда не будетвозможность приобрести замок.Подобная тупиковая ситуация все еще может возникать в некоторых случаях, если существует цикл сообщений (при просмотре передачи сообщений в виде ориентированного графа между процессами / потоками) между процессами, который препятствует получению блокировки.

Лучшая ставка для предотвращенияВ этом случае тупиковая ситуация заключается в том, чтобы избежать блокирования при выполнении вызовов MPI и вместо этого использовать неблокирующие вызовы, такие как MPI_Irecv и MPI_Test.

...