Интересно, когда мне нужно использовать барьер? Нужно ли мне это до/после разброса/сбора, например? Или должен ли OMPI обеспечить, чтобы все процессы достигли этого момента до разброса/сбора? Точно так же, после трансляции я могу ожидать, что все процессы уже получат сообщение?
Когда мне нужно использовать MPI_Barrier()?
Ответ 1
Все коллективные операции в MPI перед MPI-3.0 блокируются, что означает, что безопасно использовать все буферы, переданные им после их возврата. В частности, это означает, что все данные были получены, когда одна из этих функций возвращается. (Тем не менее, это не означает, что все данные были отправлены!) Таким образом, MPI_Barrier не требуется (или очень полезно) до/после коллективных операций, если все буферы уже действительны.
Также обратите внимание, что MPI_Barrier не волнует ожидание неблокирующих вызовов. Если вы используете неблокирующий send/recv, и оба процесса ожидают MPI_Barrier после пары send/recv, не гарантируется, что процессы отправили/получили все данные после MPI_Barrier. Вместо этого используйте MPI_Wait (и друзей). Таким образом, следующий фрагмент кода содержит ошибки:
/* ERRORNOUS CODE */
Code for Process 0:
Process 0 sends something using MPI_Isend
MPI_Barrier(MPI_COMM_WORLD);
Process 0 uses buffer passed to MPI_Isend // (!)
Code for Process 1:
Process 1 recvs something using MPI_Irecv
MPI_Barrier(MPI_COMM_WORLD);
Process 1 uses buffer passed to MPI_Irecv // (!)
Обе строки, отмеченные (!)
, небезопасны!
MPI_Barrier полезен только в нескольких случаях. В большинстве случаев вам не важно, синхронизируются ли ваши процессы. Лучше читайте о блокирующих и неблокирующих вызовах!
Ответ 2
Одним из способов использования MPI_Barrier
является, например, контроль доступа к внешнему ресурсу, например файловой системе, к которому не применяется MPI. Например, если вы хотите, чтобы каждый процесс записывал материал в файл последовательно, вы можете сделать это следующим образом:
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
for ( int ii = 0; ii < size; ++ii ) {
if ( rank == ii ) {
// my turn to write to the file
writeStuffToTheFile();
}
MPI_Barrier(MPI_COMM_WORLD);
}
Таким образом, вы можете быть уверены, что никакие два процесса одновременно не вызывают writeStuffToTheFile
.
Ответ 3
Май MPI_Barrier() не часто используется, но это полезно. Фактически, даже если вы использовали синхронную связь, MPI_Send/Recv() может только убедиться, что оба процесса синхронизированы. В моем проекте, проекте cuda + MPI, все, что я использовал, - это асинхронная связь. Я обнаружил, что в некоторых случаях, если я не использую MPI_Barrier(), за которым следует функция Wait(), ситуация, при которой два процесса (gpu) хотят передавать данные друг другу в одно и то же время, вероятно, произойдет, что может сильно снизить эффективность программы. Баг выше, чем когда-либо меня с ума сошел и взял меня на несколько дней, чтобы найти его. Поэтому вы можете подумать, используете ли MPI_Barrier(), когда вы использовали MPI_Isend/Irecv в своей программе. Иногда синхронизация процессов не только необходима, но и ДОЛЖНА, особенно программа ur работает с устройством.