Н.В. Вдовикина, И.В. Машечкин, А.Н. Терехин, А.Н. Томилин - Операционные системы - взаимодействие процессов (2008) (1114653), страница 30
Текст из файла (страница 30)
После этоговетвь с номером 0 печатает на экран аргументы командной строки.Барьерная синхронизация необходима для того, чтобы сообщения опорядковых номерах ветвей не смешивались с сообщением обобщем количестве ветвей и с выводом аргументов команднойстроки.#include <mpi.h>#include <stdio.h>int main(int argc, char **argv){int size, rank, i;MPI_Init(&argc,библиотеку */&argv);/*ИнициализируемMPI_Comm_size(MPI_COMM_WORLD, &size);/*Узнаемколичествоприложении... */задачвзапущенномMPI_Comm_rank (MPI_COMM_WORLD, &rank);/* ...и свой собственный номер: от 0 до (size1) *//* задача с номером 0 сообщает пользователюразмер группы,коммуникационный контекст которойописываеткоммуникаторMPI_COMM_WORLD,т.е.число ветвей в приложении */if (rank == 0) {printf("Totalsize );processescount=%d\n",}/* Осуществляется барьерная синхронизация187*/MPI_Barrier(MPI_COMM_WORLD);/* Теперь каждая задача выводит на экран свойномер */printf("Hello!%d\n", rank);MyrankinMPI_COMM_WORLD/* Осуществляется барьерная синхронизация=*/MPI_Barrier(MPI_COMM_WORLD);/* затем ветвь c номером 0 печатает аргументыкомандной строки.
*/if (rank == 0) {printf(“Command line of process 0:\n");for(i = 0; i < argc; i++) {printf("%d: \"%s\"\n", i, argv[i]);}}/* Все задачи завершают выполнение */MPI_Finalize();return 0;}7.2.4 Прием и передача данных. Общие замечанияПреждечемперейтикрассмотрениюфункций,непосредственно относящихся к организации обмена сообщениямимежду ветвями, остановимся на некоторых важных общихмоментах, таких как атрибуты сообщения и поддержка типизацииданных в MPI.Сообщения и их атрибутыКаждое сообщение MPI обладает следующим набороматрибутов:- номер ветви-отправителя;- номер или номера ветвей-получателей;- коммуникатор, т.е.
описатель коммуникационногоконтекста, в котором данное сообщение передается;- тип данных, образующих тело сообщения;188- количествоэлементовуказанногосоставляющих тело сообщения;типа,- тэг, или бирка сообщения.В MPI не существует специальной структуры данных,описывающей сообщение. Вместо этого, атрибуты сообщенияпередаются в соответствующие функции и получаются из них какотдельные параметры.Тэг сообщения представляет собой целое число, аналог типасообщения в механизме очередей сообщений IPC. Интерпретацияэтого атрибута целиком возлагается на саму программу.Поддержка типов данных в MPIВ отличие от других средств межпроцессного взаимодействия,рассмотренных нами ранее, в MPI требуется явное указание типаданных, образующих тело сообщения.
Причина этого заключается втом, что библиотека MPI берет на себя заботу о корректностипередачи данных в случае использования ее в гетерогенной (т.е.состоящей из разнородных узлов) среде. Одни и те же типы данныхна машинах разных архитектур могут иметь различноепредставление (к примеру, в архитектуре Intel представление целыхчисел характеризуется расположением байт от младшего кстаршему, в то время как в процессорах Motorola принято обратноерасположение; кроме того, на разных машинах один и тот же типможет иметь разную разрядность и выравнивание). Очевидно, что втакой ситуации передача данных как последовательности байт безсоответствующих преобразований приведет к их невернойинтерпретации.
Реализация MPI производит необходимыепреобразования данных в теле сообщения перед его посылкой ипосле получения, однако для этого необходима информация о типеданных, образующих тело сообщения.Для описания типов данных в MPI введен специальный тип –MPI_Datatype. Для каждого стандартного типа данных Си взаголовочном файле библиотеки описана константа типаMPI_Datatype; ее имя состоит из префикса MPI_ и имени типа,написанного большими буквами, например, MPI_INT, MPI_DOUBLE ит.д.
Кроме этого, MPI предоставляет широкие возможности поконструированию описателей производных типов, однако ихрассмотрение выходит за рамки данного пособия.Параметр типа MPI_Datatype, описывающий тип данных,образующих тело сообщения, присутствует во всех функцияхприема и передачи сообщений MPI.189Непосредственно с поддержкой типов данных MPI связанаеще одна особенность функций приема-передачи данных: в качестверазмера тела сообщения всюду фигурирует не количество байт, аколичество элементов указанного типа.7.2.5 Коммуникации «точка-точка». Блокирующий режимБиблиотека MPI предоставляет возможности для организациикак индивидуального обмена сообщениями между парой ветвей – вэтом случае у каждого сообщения имеется единственный получатель– так и коллективных коммуникаций, в которых участвуют всеветви, входящие в определенный коммуникационный контекст.Рассмотрим сначала функции MPI, используемые дляотправки и получения сообщений между двумя ветвями – такойспособ обмена в литературе часто носит название коммуникации«точка-точка».Библиотека MPI предоставляет отдельные пары функций дляреализации блокирующих и неблокирующих операций приема ипосылки данных.
Заметим, что они совместимы друг с другом влюбых комбинациях, например, для отправки сообщения можетиспользоваться блокирующая операция, а для приема этого жесообщения – неблокирующая, и наоборот.Отправка сообщений в блокирующем режимеДля отправки сообщений в блокирующем режиме служитфункция MPI_Send():#include <mpi.h>int MPI_Send(void* buf, int count, MPI_Datatypedatatype, int dest, int tag, MPI_Comm comm);Аргументы у этой функции следующие:buf – указатель на буфер, в котором расположеныданные для передачи;count – количество элементов заданного типа в буфере;datatype – тип элементов в буфере;–уникальныйномерветви-получателя.Представляет собой неотрицательное целое число в диапазоне[0, N-1], где N – число ветвей в коммуникационном контексте,описываемом коммуникатором comm;desttag – тэг (бирка) сообщения.
Представляет собойнеотрицательное целое число от 0 до некоторого максимума,190значение которого зависит от реализации (однако стандартMPI гарантирует, что этот максимум имеет значение не менее32767). Тэги сообщений могут использоваться ветвями длятого, чтобы отличать разные по смыслу сообщения друг отдруга;–коммуникатор,описывающийкоммуникационный контекст, в котором будет передаватьсясообщение.commЕще раз отметим, что в этой функции, как и во всех остальныхфункциях приема-передачи MPI, в параметре count указывается недлина буфера в байтах, а количество элементов типа datatype,образующих буфер.При вызове MPI_Send() управление возвращается процессутолько тогда, когда вызвавший процесс может повторноиспользовать буфер buf (т.е.
записывать туда другие данные) безриска испортить еще не переданное сообщение. Однако, возврат изфункции MPI_Send() не обязательно означает, что сообщение былодоставлено адресату – в реализации данной функции можетиспользоваться буферизация, т.е. тело сообщения может бытьскопировано в системный буфер, после чего происходит возврат изMPI_Send(), а сама передача будет происходить позднее васинхронном режиме.С одной стороны, буферизация при отправке позволяет ветвиотправителю сообщения продолжить выполнение, не дожидаясьмомента, когда ветвь-адресат сообщения инициирует его прием; сдругой стороны – буферизация, очевидно, увеличивает накладныерасходы как по памяти, так и по времени, так как требуетдобавочного копирования.
При использовании вызова MPI_Send()решение о том, будет ли применяться буферизация в каждомконкретном случае, принимается самой библиотекой MPI. Эторешениепринимаетсяизсоображенийнаилучшейпроизводительности, и может зависеть от размера сообщения, атакже от наличия свободного места в системном буфере. Еслибуферизация не будет применяться, то возврат управления изMPI_Send() произойдет только тогда, когда ветвь-адресатинициирует прием сообщения, и его тело будет скопировано вбуфер-приемник ветви-адресата.Режимы буферизацииMPI позволяет программисту самому управлять режимомбуферизации при отправке сообщений в блокирующем режиме.
Для191этого в MPI существуют три дополнительные модификациифункции MPI_Send(): MPI_Bsend(), MPI_Ssend() и MPI_Rsend():#include <mpi.h>int MPI_Bsend(void* buf, int count, MPI_Datatypedatatype, int dest, int tag, MPI_Comm comm);int MPI_Ssend(void* buf, int count, MPI_Datatypedatatype, int dest, int tag, MPI_Comm comm);int MPI_Rsend(void* buf, int count, MPI_Datatypedatatype, int dest, int tag, MPI_Comm comm);Их параметры полностью аналогичны MPI_Send(), различиезаключается только в режимах буферизации.предполагаетотсылкусообщениясбуферизацией. Это означает, что если к моменту вызоваMPI_Bsend() ветвь-адресат не инициировала прием сообщения, ит.о.
сообщение не может быть доставлено немедленно, оно должнобыть буферизовано. Если в буфере окажется недостаточносвободного места, MPI_Bsend() вернет ошибку. MPI предоставляетспециальные функции, с помощью которых ветвь может выделить всвоем адресном пространстве некоторый буфер, который будетиспользоваться MPI для буферизации сообщений в этом режиме,таким образом, программист может сам управлять размеромдоступного буферного пространства. Заметим, что посылкасообщения с помощью функции MPI_Bsend() является, в отличие отвсех остальных операций отсылки, локальной операцией, т.е.
еезавершение не зависит от поведения ветви-адресата.MPI_Bsend()Функция MPI_Ssend(), наоборот, представляет собой отсылкусообщения без буферизации. Возврат управления из функцииMPI_Ssend() осуществляется только тогда, когда адресатинициировал прием сообщения, и оно скопировано в буферприемник адресата. Если на принимающей стороне используетсяблокирующая функция приема сообщения, то такая коммуникацияпредставляет собой реализацию схемы рандеву: операция обмена,инициированная на любой из сторон, не завершится до тех пор, покавторая сторона также не притупит к обмену.Вызов функции MPI_Rsend() сообщает MPI о том, что ветвьадресат уже инициировала запрос на прием сообщения.