Это часть кода.
if(rank==0) {
temp=10000;
var=new char[temp] ;
MPI_Send(&temp,1,MPI_INT,1,tag,MPI_COMM_WORLD);
MPI_Send(var,temp,MPI_BYTE,1,tag,MPI_COMM_WORLD);
//MPI_Wait(&req[0],&sta[1]);
}
if(rank==1) {
MPI_Irecv(&temp,1,MPI_INT,0,tag,MPI_COMM_WORLD,&req[0]);
MPI_Wait(&req[0],&sta[0]);
var=new char[temp] ;
MPI_Irecv(var,temp,MPI_BYTE,0,tag,MPI_COMM_WORLD,&req[1]);
MPI_Wait(&req[0],&sta[0]);
}
//I am talking about this MPI_BarrierMPI_Barrier(MPI_COMM_WORLD);
cout << MPI_Wtime()-t1 << endl ;
cout << "hello " << rank << " " << temp << endl ;
MPI_Finalize();
}
1. при использовании MPI_Barrier — Как и ожидалось, весь процесс занимает почти одинаковое количество времени, порядка 0,02.
2. когда не используется MPI_Barrier () — корневой процесс (отправка сообщения) ждет дополнительного времени.
и (MPI_Wtime -t1)
сильно варьируется, а время, затрачиваемое корневым процессом, составляет порядка 2 секунд.
Если я не ошибаюсь, MPI_Barrier используется только для приведения всех запущенных процессов на одном уровне. так почему же время, когда я использую MPI_Barrier (), не составляет 2 секунды (минимум всех процессов, т. е. корневой процесс). Пожалуйста, объясни ?
Спасибо Уэсли Блэнду за то, что он заметил, что вы ждете дважды по одному и тому же запросу. Вот объяснение того, что на самом деле происходит.
Есть что-то под названием прогрессия асинхронных (неблокирующих) операций в MPI. Именно тогда происходит фактическая передача. Прогрессирование может происходить разными способами и в разных точках библиотеки MPI. Когда вы публикуете асинхронную операцию, ее выполнение может быть отложено на неопределенное время, даже до точки, которую вы вызываете MPI_Wait
, MPI_Test
или некоторый вызов, который привел бы к тому, что новые сообщения были отправлены или извлечены из очереди приема / передачи. Вот почему очень важно позвонить MPI_Wait
или же MPI_Test
как можно быстрее после начала неблокирующей операции.
Открытый MPI поддерживает поток фоновой прогрессии, который заботится о продвижении операций, даже если условие в предыдущем абзаце не выполняется, например, если MPI_Wait
или же MPI_Test
никогда не вызывается в дескрипторе запроса. Это должно быть явно включено при сборке библиотеки. Он не включен по умолчанию, так как фоновая прогрессия увеличивает задержку операций.
Что происходит в вашем случае, так это то, что вы ожидаете неверный запрос при втором звонке MPI_Wait
в приемнике, следовательно, прогрессия второго MPI_Irecv
операция откладывается. Размер сообщения превышает 40 КиБ (10000 × 4 байта + издержки конверта), что превышает предельное значение по умолчанию в Open MPI (32 КиБ). Такие сообщения отправляются с использованием протокола рандеву, который требует отправки и выполнения операций отправки и получения. Операция приема не продвигается и, следовательно, операция отправки в блоках ранга 0 до тех пор, пока в какой-то момент времени процедуры очистки, которые MPI_Finalize
в ранге 1 звонки в конечном счете прогрессируют получение
Когда вы положите вызов MPI_Barrier
это приводит к прогрессированию выдающегося приема, действующего почти как неявный призыв к MPI_Wait
, Вот почему отправка в ранге 0 завершается быстро, и оба процесса идут вовремя.
Обратите внимание, что MPI_Irecv
сразу после MPI_Wait
эквивалентно простому звонку MPI_Recv
, Последнее не только проще, но и менее подвержено простым опечаткам, подобным тому, который вы сделали.
Ты ждешь по одному и тому же запросу два раза для твоего Irecv. второй — тот, который занимал бы все время, и с тех пор, как его пропустили, ранг 0 становится намного впереди.
MPI_BARRIER может быть реализован так, что некоторые процессы могут выходить из алгоритма раньше остальных, если процессы входят в него. Это, наверное, то, что здесь происходит.
В тестах, которые я провел, я не вижу почти никакой разницы во времени выполнения. Основное отличие состоит в том, что вы, кажется, выполняете свой код один раз, тогда как я повторял ваш код тысячи раз, а затем взял среднее значение. Мой вывод ниже:
With the barrier
[0]: 1.65071e-05
[1]: 1.66872e-05
Without the barrier
[0]: 1.35653e-05
[1]: 1.30711e-05
Поэтому я бы предположил, что любые изменения, которые вы видите, являются результатом вашей операционной системы, а не вашей программы.
Кроме того, почему вы используете MPI_Irecv в сочетании с MPI_wait, а не просто MPI_recv?