Цель этого расширения 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 должна
гарантировать, что блокированный пользовательский вычислительный процесс
возобновится.