next up previous contents
Next: Регистры и компайлер-оптимизации Up: Семантика и правильность Previous: Атомарность   Contents

Процесс выполнения

Односторонние коммуникации предъявляют те же требования к процессу выполнения, что и двухточечные коммуникации: как только взаимодействие становится возможным, гарантируется, что оно выполнится. RMA вызовы должны иметь локальную семантику, за исключением тех случаев, когда это необходимо для синхронизации с другими RMA вызовами.

Существует некоторая нечеткость в определении времени, когда RMA коммуникации становятся возможным. Эта нечеткость обеспечивет разработчику большую гибкость, чем двухточечные коммуникации. Доступ к окну адресата становится возможным, как только выполнится соответствующая синхронизация (такая как MPI_WIN_FENCE или MPI_WIN_POST). В инициаторе RMA коммуникации могут стать возможными сразу же, как только выполнится соответствующий вызов get, put или accumulate, или после того, как будет выполнен следующий синхронизационный вызов. Коммуникации должны выполняться, как только они станут возможными как для инициатора, так и для адресата.

Рассмотрим фрагмент кода в примере 4.4. Некоторые вызовы могут выполнять блокирование, если окно адресата не предоставлено для доступа. Однако, если окно адресата предоставлено для доступа, тогда фрагмент кода должен выполниться. Передача данных может начаться, как только произойдет вызов put, но может быть отложена до тех пор, пока не произойдет соответствующий вызов complete.

Рассмотрим фрагмент кода в примере 4.5. Некоторые вызовы могут выполнять блокирование, если другой процесс удерживает конфликтующую блокировку. Однако, если конфликтующая блокировка не держится, тогда фрагмент кода должен выполниться.

\includegraphics[scale=0.70]{pic/6.6.eps}


Рисунок 6.6. Симметричные коммуникации

Рассмотрим код, проиллюстрированный на рис. 6.6. Каждый процесс обновляет окно другого процесса, используя операцию put, затем обращается к собственному окну. Вызовы post не блокирующие, и должны выполниться. Как только произошел вызов post, RMA доступ к окну установлен, так что каждый процесс должен выполнить последовательность вызовов start-put-complete. Как только это сделано, должны выполниться вызовы wait на обоих процессах. Таким образом, это взаимодействие не должно зайти в тупик, невзирая на количество переданных данных.

Предположим, в последнем примере, что порядок вызовов post и START обратен на каждом процессе. Тогда код может зайти в тупик, так как каждый процесс может блокироваться на вызове start, ожидая пока не произойдет сооветствующий вызов post. Так же, программа зайдет в тупик, если порядок вызовов complete и wait обратен на каждом процессе.

\includegraphics[scale=0.70]{pic/6.7.eps}


Рисунок 6.7. Ситуация взаимоблокировки

Следующие два примера иллюстрируют факт, что синхронизация между complete и wait несимметричная: вызов wait блокируется, пока выполняется complete, но не наоборот. Рассмотрим код, иллюстрированный на рис 6.7. Этот код зайдет в тупик: wait процесса 1 блокируется, пока не выполнятся вызовы процесса 0, и receive процесса 0 блокируется, пока процесс 1 вызывает send.

\includegraphics[scale=0.70]{pic/6.8.eps}


Рисунок 6.8. Ситуация без взаимоблокировки.

Рассмотрим, с другой стороны, код, проиллюстрированный на рис 6.8. Этот код не зайдет в тупик. Как только процесс 1 вызывает post, тогда последовательность start, put, complete на процессе 0 может продолжаться до завершения. Процесс 0 достигнет вызова send, позволяя выполниться вызову receive процесса 1.

Объяснение: MPI реализации должны гарантировать, что процесс делает PROGRESS на всех установленных взаимодействиях, в которых он принимает участие, пока заблокирован на MPI вызове. Это справедливо для SEND-RECEIVE взаимодействия и также касается RMA взаимодействия. Таким образом, в примере на рис 6.8, вызовы put и complete процесса 0 должны выполниться, пока процесс 1 блокирован на вызове receive. Это может потребовать участия процесса 1, например, чтобы передать данные put, пока он заблокирован на вызове receive.

Подобный вопрос состоит в том, должно ли происходить такое выполнение в то время, когда процесс занят вычислением, или блокирован в не-MPI вызове? Предположим, что в последнем примере пара send-receive заменяется на пару write-to-socket/read-from-socket. Тогда MPI не определяет, удалось ли избежать взаимной блокировки (deadlock). Предположим, что блокирующий receive процесса 1 заменен на очень длинный вычисляющий цикл. Тогда, в соответствии с интерпретацией MPI стандарта, процесс 0 должен вернуться из выполнения вызова после ограниченной задержки, даже если процесс 1 не достиг какого-нибудь MPI вызова в этот период времени. В соответствии с другой интерпретацией, вызов complete может блокироваться, пока процесс 1 не достигнет вызова wait, или не достигнет другого MPI вызова. Если процесс попал в бесконечный вычислительный цикл, качественное поведение одинаково в обеих интерпретациях: в этом случае разница не имеет значения. Тем не менее, количественные ожидания различны. Разные MPI реализации отображают эти разные интерпретации. В то время, как эта двусмысленность неудачна, она, кажется, не затрагивает многие реальные коды. MPI форум решил не фиксировать, какая интерпретация стандарта является правильной, так как проблема очень спорна, и решение больше влияло бы на разработчиков, и меньше на пользователей. []



Alex Otwagin 2002-12-10