Интересно, когда мне нужно использовать барьер? Нужно ли мне это, например, до/после разброса/сбора? Или OMPI должен убедиться, что все процессы достигли этой точки, прежде чем разбрасывать/собирать? Аналогично, могу ли я ожидать, что после широковещательной рассылки все процессы уже получат сообщение?
Когда мне нужно использовать MPI_Barrier()?
Ответы (3)
Все коллективные операции в MPI до MPI-3.0 являются блокирующими, а это означает, что безопасно использовать все переданные им буферы после их возврата. В частности, это означает, что все данные были получены при возврате одной из этих функций. (Однако это не означает, что все данные были отправлены!) Таким образом, MPI_Barrier не нужен (или очень полезен) до/после коллективных операций, если все буферы уже действительны.
Также обратите внимание, что MPI_Barrier не ожидает волшебным образом неблокирующих вызовов. Если вы используете неблокирующую отправку/получение и оба процесса ожидают на 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 полезен только в нескольких случаях. Большую часть времени вам все равно, синхронизируются ли ваши процессы. Лучше почитайте про блокировку и неблокировку звонков!
(!)
является ошибкой? Процесс 0 по-прежнему будет иметь свой собственный буфер? Кроме того, поскольку это отправка, принимающая сторона не изменит его, верно?
- person Jiew Meng; 09.11.2012
(!)
, вы можете отправить что-то другое. Я не совсем уверен в этом, но думаю, что поведение в данном случае не определено.
- person Markus Mayr; 09.11.2012
send
(потому что именно в этом заключается блокировка), потому что он копируется MPI (не обязательно в том же как для буферизованной отправки MPI_Bsend
)? Конечно, правильно, что при блокировке возврата отправки мы не можем быть уверены, что данные были получены.
- person falconepl; 13.03.2015
Одним из вариантов использования 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
.
Может MPI_Barrier() используется не часто, но полезно. На самом деле, даже если вы использовали синхронную связь, MPI_Send/Recv() может только обеспечить синхронизацию двух процессов. В моем проекте cuda+MPI я использовал только асинхронную связь. Я обнаружил, что в некоторых случаях, если я не использую MPI_Barrier(), за которой следует функция Wait(), очень вероятно, что два процесса (gpu) хотят передавать данные друг другу одновременно, что может привести к серьезным последствиям. снизить эффективность программы. Вышеупомянутая ошибка всегда приводила меня в бешенство, и мне потребовалось несколько дней, чтобы найти ее. Поэтому вы можете тщательно подумать, использовать ли MPI_Barrier(), когда вы используете MPI_Isend/Irecv в своей программе. Иногда синхронизация процессов не только необходима, но и ОБЯЗАТЕЛЬНА, особенно ваша программа работает с устройством.