Поэтому совсем недавно я разрабатывал некоторые асинхронные алгоритмы в своих исследованиях. Я проводил несколько параллельных исследований производительности и подозревал, что неправильно понимаю некоторые детали различных неблокирующих функций MPI.
Я видел несколько проницательных сообщений здесь, а именно:
Есть несколько вещей, в которых я не уверен или просто хочу прояснить, связанные с работой с неблокирующими функциями, которые, я думаю, помогут мне потенциально повысить производительность моего текущего программного обеспечения.
Из части Неблокирующая связь стандарта MPI 3.0:
A nonblocking send start call initiates the send operation, but does not complete it. The send start call can return before the message was copied out of the send buffer. A separate send complete call is needed to complete the communication, i.e., to verify that the data has been copied out of the send buffer. With suitable hardware, the transfer of data out of the sender memory may proceed concurrently with computations done at the sender after the send was initiated and before it completed.
...
If the send mode is standard then the send-complete call may return before a matching receive is posted, if the message is buffered. On the other hand, the receive-complete may not complete until a matching receive is posted, and the message was copied into the receive buffer.
Итак, в качестве первого набора вопросов о MPI_Isend
(и аналогично MPI_Irecv
), кажется, что для обеспечения завершения неблокирующей отправки мне нужно использовать какой-то механизм для чек об оплате, чтобы он был завершен, потому что в худшем случае будет может нет. подходящее оборудование для одновременной передачи данных, верно? Так что, если я никогда не использую что-то вроде MPI_Test
или MPI_Wait
после неблокирующей отправки, MPI_Isend
может никогда не получить свое сообщение, верно?
Этот вопрос относится к некоторым из моих работ, потому что я отправляю сообщения через MPI_Isend
и на самом деле не проверяю полноту, пока не получу ожидаемое ответное сообщение, потому что я хочу избежать накладных расходов на вызовы MPI_Test
. Хотя этот подход работает, судя по моему чтению, он кажется ошибочным.
Кроме того, во втором абзаце говорится, что для стандартной неблокирующей отправки MPI_Isend
он может нет даже начинает отправлять любые свои данные до тех пор, пока процесс назначения не вызовет соответствующий прием. Учитывая доступность MPI_Probe
/MPI_Iprobe
, означает ли это, что вызов MPI_Isend
по меньшей мере отправит некоторые предварительные метаданные сообщения, такие как размер, источник и тег, чтобы функции проверки в целевом процессе могли знать, что сообщение хочет быть отправлено туда, и поэтому процесс назначения может фактически опубликовать соответствующее получение?
В связи с этим вопрос о зонде. В разделе Зондировать и отменить стандарт говорит, что
MPI_IPROBE(source, tag, comm, flag, status)
returnsflag = true
if there is a message that can be received and that matches the pattern specifed by the argumentssource
,tag
, andcomm
. The call matches the same message that would have been received by a call toMPI_RECV(..., source, tag, comm, status)
executed at the same point in the program, and returns in status the same value that would have been returned byMPI_RECV()
. Otherwise, the call returnsflag = false
, and leavesstatus
undefined.
Исходя из приведенного выше отрывка, становится ясно, что проверка сообщит вам, есть ли доступное сообщение, которое вы можете получить, соответствующее указанным source
, tag
и comm
. Мой вопрос: должны ли вы предполагать, что данные для соответствующей отправки из успешного зондирования еще не были переданы?
Теперь, после прочтения стандарта, мне кажется разумным, что действительно сообщение, известное зонду, не обязательно должно быть сообщением, которое фактически полностью получено локальным процессом. Учитывая предыдущие сведения о стандартной неблокирующей отправке, кажется, что вам нужно опубликовать получение после выполнения проверки, чтобы гарантировать завершение исходной неблокирующей стандартной отправки, потому что могут быть случаи, когда источник отправляет большое сообщение что MPI не хочет копировать в какой-то внутренний буфер, верно? И в любом случае, кажется, что публикация получения после проверки — это то, как вы гарантируете, что вы действительно получите полные данные из соответствующей отправки для отправки. Это правильно?
Этот последний вопрос относится к одному экземпляру в моем коде, где я выполняю вызов MPI_Iprobe
, и если это удается, я выполняю вызов MPI_Recv
, чтобы получить сообщение. Тем не менее, я думаю, что сейчас это может быть проблематично, потому что я думал, что если зонд увенчается успехом, это означает, что он уже получил все сообщение. Это означало, что MPI_Recv
будет работать быстро, так как полное сообщение уже где-то в локальной памяти. Однако теперь я чувствую, что это было неверное предположение, и некоторые разъяснения были бы полезны.
Стандарт MPI не требует наличия потока выполнения. Это означает, что MPI_Isend()
может вообще ничего не делать, пока общение не будет продолжено. Прогресс происходит под капотом большинства подпрограмм MPI, MPI_Test()
, MPI_Wait()
и MPI_Probe()
являются наиболее очевидными.
Боюсь, вы смешиваете прогресс и синхронную отправку (например, MPI_Ssend()
).
MPI_Probe()
— это локальная операция, это означает, что она не будет связываться с отправителем и спрашивать, было ли что-то отправлено, или продвигать это.
Что касается производительности, вы должны, насколько это возможно, избегать неожиданных сообщений, это означает, что получение должно быть отправлено на одном конце до того, как сообщение будет отправлено на другом конце.
Здесь существует компромисс между производительностью и переносимостью:
Имейте в виду, что большинство реализаций MPI (читайте, что это не предусмотрено стандартом MPI, и вы не должны полагаться на него) отправляют небольшие сообщения в активном режиме.
Это означает, что MPI_Send()
, скорее всего, вернется немедленно, если сообщение достаточно маленькое (а достаточно маленькое зависит, среди прочего, от вашей реализации MPI, от того, как она настроена или от того, какое межсоединение используется).
если вы не знаете максимальный размер получаемого сообщения, вы можете использовать MPI_Probe()
, выделить буфер нужного размера, а затем MPI_Recv()
. В противном случае вы можете рассмотреть возможность пересмотра своего алгоритма. MPI_Send()
возвращается, когда буфер отправки можно использовать повторно, и нет гарантии, что соответствующий прием был отправлен или что сообщение покинуло хост. MPI_Ssend()
возвращает, когда буфер отправки может быть повторно использован а также, отправка сообщения была начата из-за соответствующего приема.
Спасибо за всю эту информацию, она оказалась весьма полезной. Пример моей ситуации: я построил распределенный контейнер, аналогичный массиву. Этот контейнер распределяет данные по коммуникатору процессов и позволяет, например, запрашивать данные внутри этого контейнера по некоторому индексу. Чаще всего индекс приводит к запросу данных из другого процесса. Насколько я понимаю, каждый процесс должен проверять, просто чтобы узнать, не запрашивает ли какой-либо другой процесс доступ к некоторым данным, поскольку он не может предсказать это заранее. Видите ли вы альтернативу этому подходу?
MPI
хорошо подходит для отправки/получения или коллективных операций. Обычно вы бы MPI_Scatter()
данные и MPI_Gather()
результаты. Согласно вашему описанию, вы можете рассмотреть односторонние операции (MPI_Put()
и MPI_Get()
) или альтернативы без MPI, такие как PGAS (OpenSHMEM, ко-массивы Fortran, ...). MPI, как правило, не подходит для обработки событий.
Возможно, мне придется взглянуть на односторонние операции, чтобы увидеть, смогу ли я заставить что-то подобное работать в моей ситуации, но ваше последнее утверждение определенно заставляет меня задуматься, будет ли MPI достаточно хорош с точки зрения производительности. Большое спасибо за ваши идеи и мысли!
Ответ правильный и хороший, но я чувствую, что некоторые моменты немного неясны. Хотя MPI не требует прогресса нить, он делает гарантировать прогресс (в конце концов). Конечно, вам не нужна программа, работающая только после долгой задержки, потому что вызов MPI не выполняется. Но приятно знать, что вам не нужно завершать асинхронную отправку, чтобы добиться прогресса в этой отправке. Для второй части гарантия прогресса (для отправки) на самом деле зависит от "соответствующий прием был запущен". Таким образом, поскольку MPI_Probe
не запускает прием, это не гарантирует прогресс.
@Zulan спасибо за ваши дальнейшие комментарии, особенно за ваш первый вопрос о прогрессе!
Большое спасибо за ваш ответ, я думаю, что вы дали мне несколько полезных ответов на мои вопросы. Можете ли вы объяснить, что вы имели в виду, когда сказали, что я смешиваю концепции прогресса с синхронной отправкой? И зондирование в основном делается для того, чтобы справиться с ситуацией, когда вы знаете, что можете получить неожиданные сообщения, верно? В противном случае вы, как правило, знали бы, что нужно просто опубликовать соответствующий набор сообщений без необходимости проверки, верно?