next up previous contents
Next: Примеры Up: Внешние интерфейсы Previous: Введение   Contents

Обобщенные запросы

Цель этого расширения MPI-2 состоит в том, чтобы позволить пользователям определять новые неблокирующие операции. Такие замечательные операции представлены (обобщенными) запросами. Фундаментальным свойством неблокирующих операций является то, что продвижение к моменту их выполнения происходит асинхронно, то есть одновременно с нормальным выполнением программы. Как правило, это требует выполнения кода одновременно с выполнением пользовательского кода, например, в отдельной нити или в обработчике сигнала. Операционные системы предоставляют ряд механизмов для поддержки одновременного выполнения. MPI не пытается стандартизировать или заменить эти механизмы: считается, что программисты, которые желают определить новые асинхронные операции, будут использовать для этого механизмы, предоставляемые операционной системой на более низком уровне. Так, вызовы, описанные в этой секции, являются средством только для определения эффективности таких вызовов MPI, как MPI_WAIT или MPI_CANCEL, когда они применяются в обобщенных запросах, и для посылки сигнала MPI о завершении обобщенного запроса.

Объяснение:

Сказанное выше подталкивает к тому, чтобы также определить в MPI стандартный механизм для достижения одновременного выполнения определенных пользователем неблокирующих операций. Однако, очень трудно определить такой механизм без рассмотрения специфических механизмов, используемых в операционных системах. Участники MPI Forum понимали, что механизмы распараллеливания являются неотъемлимой частью находящейся на более низком уровне операционной системы и не должны быть стандартизированы MPI; стандарт MPI должен только оговаривать взаимодействие с такими механизмами.

В случае правильного запроса операция, связанная с этим запросом, выполняется данной реализацией MPI и завершается без вмешательста приложения. Для обобщенного запроса операция, связанная с этим запросом, выполняется приложением, поэтому приложение должно сообщить MPI когда операция завершится. Это достигается отработкой вызова MPI_GREQUEST_COMPLETE. MPI обрабатывает статус ``завершения'' обобщенного запроса. Любой другой статус запроса должен быть обработан пользователем.

Новый обобщенный запрос стартует при:

MPI_GREQUEST_START(query_fn, free_fn, cancel_fn, extra_state, request)

IN query_fn функция, вызываемая когда требуется статус запроса

(функция)

 
IN free_fn функция, вызываемая когда запрос освобожден (функция)  
IN extra_state функция, вызываемая когда запрос отменен (функция)

 
OUT request Обобщенный запрос (обработчик)  

int MPI_Grequest_start(MPI_Grequest_query_function *query_fn, MPI_Grequest_free_function *free_fn, MPI_Grequest_cancel_function *cancel_fn, void *extra_state, MPI_Request *request)

MPI_GREQUEST_START(QUERY_FN, FREE_FN, CANCEL_FN, EXTRA_STATE, REQUEST, IERROR) INTEGER REQUEST, IERROR EXTERNAL QUERY_FN, FREE_FN, CANCEL_FN INTEGER (KIND=MPI_ADDRESS_KIND) EXTRA_STATE

static MPI::Grequest MPI::Grequest::Start(const MPI::Grequest::Query_function query_fn, const MPI::Grequest::Free_function free_fn, const MPI::Grequest::Cancel_function cancel_fn, void* extra_state)

Совет пользователям: Обратите внимание на то, что обобщенный запрос принадлежит в С++ к классу MPI::Grequest, который является производным от класса MPI::Request. Он относится к тому же типу, что и правильные запросы в Си и ФОРТРАНe.

Вызов запускает обобщенный запрос и возвращает указатель на него.

Синтаксис и описание возвратных функций приводятся ниже. Всем возвратным функциям передается аргумент extra_state, который связывается с запросом во время начала работы запроса MPI_GREQUEST_START. Это может использоваться для обработки определяемых пользователем состояний для запроса. На Си требуется функция:

typedef int MPI_Grequest_query_function(void *extra_state, MPI_Status *status);

На ФОРТРАНe:

SUBROUTINE GREQUEST_QUERY_FUNCTION(EXTRA_STATE, STATUS, IERROR) INTEGER STATUS(MPI_STATUS_SIZE), IERROR INTEGER(KIND=MPI_ADDRESS_KIND) EXTRA_STATE

И на С++:

typedef int MPI::Grequest::Query_function(void* extra_state, MPI::Status& status);

Функция query_fn вычисляет состояние, которое должно быть возвращено для обобщенного запроса. Состояние также включает информацию об успешной или неудачной отмене запроса (результат, который будет возвращен MPI_TEST_CANCELLED).

Функция query_fn вызывается MPI_{WAIT|TEST}{ANY|SOME|ALL} вызовом, который завершает
обобщенный запрос, связанный с этим отзывом. Функция также запускается вызовами
MPI_REQUEST_GET_STATUS, если запрос выполнен, когда происходит вызов. В обоих случаях, в возвратную функцию передается ссылка на соответствующую переменную состояния, передаваемую пользователем при вызове MPI; состояние, установленное возвратной функцией, возвращается вызовом MPI. Даже если пользователь предусмотрел MPI_STATUS_IGNORE или MPI_STATUSES_IGNORE для функции

MPI, которая обязательно вызовет query_fn, MPI передаст достоверное состояние объекта в query_fn, но проигнорирует его при возврате из возвратной функции. Заметьте, что query_fn вызывается только после MPI_GREQUEST_COMPLETE, в свою очередь вызванного при запросе; она может быть вызвана несколько раз для одного и того же обобщенного запроса, например, если пользователь несколько раз вызывает MPI_REQUEST_GET_STATUS для этого запроса. Заметьте также, что вызов MPI_{WAIT|TEST}{SOME|ALL} может породить многократные вызовы query_fn возвратной функции, один раз для каждого обобщенного запроса, который завершен вызовом MPI. Порядок этих вызовов MPI не регламентируется.

На Си функция освобождения имеет вид:

typedef int MPI_Grequest_free_function(void *extra_state);

На ФОРТРАНe:

SUBROUTINE GREQUEST_FREE_FUNCTION(EXTRA_STATE, IERROR) INTEGER IERROR INTEGER(KIND=MPI_ADDRESS_KIND) EXTRA_STATE

и на С++:

typedef int MPI::Grequest::Free_function(void* extra-state);

Функция free_fn вызывается для того, чтобы очистить распределенные пользователем ресурсы, когда обобщенный запрос освобожден.

Возвратная функция free_fn вызывается MPI_{WAIT|TEST}{ANY|SOME|ALL} вызовом, который закончил обобщенный запрос, связанный с этой возвратной функцией. free_fn вызывается после вызова query_fn для того же самого запроса. Однако, если вызов MPI закончил многократные обобщенные запросы, порядок, в котором вызываются возвратные free_fn функции, MPI не регламентируется.

Возвратная функция free_fn также вызывается для обобщенных запросов, которые освобождены вызовом MPI_REQUEST_FREE (вызова MPI_{WAIT|TEST}{ANY|SOME|ALL} не произойдет для такого запроса). В этом случае возвратная функция будет вызвана в вызове MPI_REQUEST_FREE(request), или в вызове MPI_GREQUEST_COMPLETE(request), какой бы из них не произошел последним. То есть, в этом случае фактическое освобождение для кода происходит как только происходят оба запроса MPI_REQUEST_FREE и MPI_GREQUEST_COMPLETE. Запрос является нераспределенным до выполнения free_fn. Обратите внимание, что free_fn в корректной программе будет вызываться в запросе только однажды.

Совет пользователям: Вызов MPI_REQUEST_FREE(request) установит указатель запроса в
MPI_REQUEST_NULL. Этот указатель на обобщенный запрос станет недостоверным. Однако, другие пользовательские копии этого указателя являются достоверными до завершения работы free_fn с того момента, когда MPI уже не распределяет эти объекты. С этого момента free_fn не вызывается до завершения MPI_GREQUEST_COMPLETE, пользовательская копия указателя может использоваться, чтобы сделать этот запрос. Пользователи должны обратить внимание на то, что MPI будет распределять объект после того, как free_fn выполнится. В этот момент, пользовательские копии указателя запроса больше не указывают на достоверный запрос. MPI не будет устанавливать в этом случае пользовательские копии в MPI_REQUEST_NULL, так что пользователю нужно избегать обращений к этому устаревшему указателю. Возникает особый случай, когда MPI задерживает распределение объекта некоторое время, в течение которого пользователи еще не знают об этом.

На Си функция отмены:

typedef int MPI_Grequest_cancel_function(void *extra_state, int complete);

На ФОРТРАНe:

SUBROUTINE GREQUEST_CANCEL_FUNCTION(EXTRA_STATE, COMPLETE, IERROR) INTEGER IERROR INTEGER(KIND=MPI_ADDRESS_KIND) EXTRA_STATE LOGICAL COMPLETE

И на С++:

typedef int MPI::Grequest::Cancel_function(void* extra_state, bool complete);

Функция cancel_fn вызывается, чтобы инициировать отмену обобщенного запроса. Она вызывается MPI_REQUEST_CANCEL(request). MPI передает возвратной функции complete=true, если
MPI_GREQUEST_COMPLETE уже был вызван для запроса , и complete=false, в противном случае.

Все возвратные функции возвращают соответствующий код ошибки. Код передается назад в функцию MPI, которая вызвала данную возвратную функцию, и соответственно имела дело с кодом ошибки. Например, если коды ошибки возвращены, то код ошибки, возвращенный возвратной функцией, будет передан функции MPI, которая вызвала эту возвратную функцию. В случае вызова MPI_{WAIT|TEST}_ANY, который в свою очередь вызывает обе функции query_fn и free_fn, вызов MPI вернет код ошибки, возвращенный последней возвратной функцией, а именно free_fn. Если в одном или большем количестве запросов в вызове MPI_{WAIT|TEST}{SOME|ALL} произошли ошибки, то вызов MPI вернет MPI_ERR_IN_STATUS. В подобном случае, если вызову MPI был передан массив состояний, то MPI вернет в каждом из состояний, которое адресовано завершенному обобщенному запросу, код ошибки, возвращенный соответствующим обращением к его возвратной free_fn функции. Однако, если в функцию MPI был передан MPI_STATUSES_IGNORE, то индивидуальные коды ошибки, возвращенные каждой из возвратных функций, будут потеряны.

Совет пользователям: query_fn не должна устанавливать поле ошибки в статусе, так как query_fn может вызываться MPI_WAIT или MPI_TEST, при этом поле ошибки в статусе не должно изменяться. Библиотека MPI определяет ``контекст'', в котором вызывается query_fn и может правильно решить, когда поместить в поле ошибки статуса возвращенный код ошибки.

MPI_GREQUEST_COMPLETE(request)

INOUT request Обобщенный запрос (обработчик)  

int MPI_Grequest_complete(MPI_Request request)

\verb|MPI_GREQUEST_COMPLETE|(REQUEST, IERROR) INTEGER REQUEST, IERROR

void MPI::Grequest::Complete()

Запрос информирует MPI о том, что операции, порожденные обобщенным запросом, выполнились. (См. определения в секции 1.4). Вызов MPI_WAIT(request, status) будет вызван и вызов MPI_TEST(request, flag, status) вернет flag=true только после того, как вызов
MPI_GREQUEST_COMPLETE объявил, что эти операции выполнены.

Однако, новые неблокирующие операции должны быть определены так, чтобы MPI в общем не накладывал никаких ограничений на код, выполняемый возвратными функциями, семантические правила вызовов MPI, таких как MPI_TEST, MPI_REQUEST_FREE или MPI_CANCEL все еще сохраняются. Например, считается, что все эти запросы являются локальными и неблокирующими. Поэтому, функции query_fn, free_fn, или cancel_fn должны вызывать блокирующие коммуникационные вызовы MPI только в таком контексте, когда эти вызовы гарантированно отработают за конечное время. Отменяемая с помощью одного вызова MPI_CANCEL операция должна завершиться за конечное временя, независимо от состояния других процессов (операция приобретает ``локальную'' семантику). Она должно или успешно выполниться, или потерпеть неудачу без побочных эффектов. Пользователь должен гарантировать такие же свойства для вновь определяемых операций.

Совет разработчикам: Вызов MPI_GREQUEST_COMPLETE может разблокировать заблокированный пользовательский процесс или нить. Библиотека MPI должна гарантировать, что блокированный пользовательский вычислительный процесс возобновится.



Subsections
next up previous contents
Next: Примеры Up: Внешние интерфейсы Previous: Введение   Contents
Alex Otwagin 2002-12-10