
Программирование для многопроцессорных систем в стандарте MPI - Шпаковский Г.И., Серикова Н.В
..pdfСостояние: |
Время: |
Broadcast |
0.000184 |
Compute |
4.980584 |
Reduce |
0.000248 |
Sync |
0.000095 |
Сумма: |
4.981111 |
Такая итоговая информация является довольно рaспространенной, но грубой формой профилирования; она сообщает только, где программа тратит время. Значительно информативнее графическое представление, обеспечиваемое специализированными программами, на-
пример, upshot и jampshot.
Входные процедуры MPE используются, чтобы создать логфайлы (отчеты) о событиях, которые имели место при выполнении параллельной программы. Форматы этих процедур представлены ниже.
Форматы для С int MPE_Init_log (void) int MPE_Start_log (void) int MPE_Stop_log (void)
int MPE_Finish_log (char *logfilename)
int MPE_Describe_state (int start, int end, char *name, char *color) int MPE_Describe_event (int event, char *name)
int MPE_Log_event (int event, int intdata char *chardata)
Форматы для Fortran
MPE_INIT_LOG( ) MPE_FINISH_LOG (LOGFILENAME)
CHARACTER*(*) LOGFILENAME
MPE_START_LOG ( )
MPE_STOP_LOG ( )
MPE-DESCRIBE_STATE(START, END, NAME, COLOR) INTEGER START, END
CHARACTER*(*) NAME, COLOR
MPE_DESCRIBE_EVENT(EVENT, NAME) INTEGER EVENT
CHARACTER*(*) NAME MPE_LOG_EVENT(EVENT, INTDATA, CHARDATA) INTEGER EVENT,
INTDATA CHARACTER*(*) CHARDATA
Эти процедуры позволяют пользователю включать только те события, которые ему интересны в данной программе. Базовые проце-
дуры − MPE_Init_log, MPE_Log_event и MPE_Finish_log.
41
MPE_Init_log должна вызываться всеми процессами, чтобы инициализировать необходимые структуры данных. MPE_Finish_log собирает отчеты из всех процессов, объединяет их, выравнивает по общей шкале времени. Затем процесс с номером 0 в коммуникаторе MPI_COMM_WORLD записывает отчет в файл, имя которого указано в аргументе. Одиночное событие устанавливается процедурой MPE_Log_event, которая задает тип события (выбирает пользователь), целое число и строку для данных. Чтобы разместить логфайл, который будет нужен для анализа или для программы визуализации (подобной upshot), процедура MPE_Describe_state позволяет добавить события и описываемые состояния, указать точку старта и окончания для каждого состояния. При желании для визуализации отчета можно использовать цвет. MPE_Stop_log и MPE_Start_log предназначены для того, чтобы динамически включать и выключать создание отчета.
Эти процедуры используются в одной из профилирующих библиотек, поставляемых с дистрибутивом для автоматического запуска событий библиотечных вызовов MPI.
Две переменные среды TMPDIR и MPE LOG FORMAT нужны пользователю для установки некоторых параметров перед генерацией логфайлов.
MPE LOG FORMAT – определяет формат логфайла, полученного после исполнения приложения, связанного с MPE–библиотекой. MPE LOG FORMAT может принимать только значения CLOG, SLOG и ALOG. Когда MPE LOG FORMAT установлен в NOT, предполагается формат CLOG.
TMPDIR – описывает директорий, который используется как временная память для каждого процесса. По умолчанию, когда TMPDIR есть NOT, будет использоваться “/tmp”. Когда пользователю нужно получить очень длинный логфайл для очень длинной MPI–работы, пользователь должен убедиться, что TMPDIR достаточно велик, чтобы хранить временный логфайл, который будет удален, если объединенный файл будет создан успешно.
2.4. СРЕДСТВА ПРОСМОТРА ЛОГФАЙЛОВ
Существует четыре графических средства визуализации, распро-
страняемых вместе с MPE: upshot, nupshot, Jumpshot-2 и Jumpshot-3.
Из этих четырех просмотрщиков логфайлов только три построены с помощью MPE. Это upshot, Jumpshot-2 и Jumpshot-3.
42

Upshot и Nupshot. Один из используемых инструментов называется upshot. Самый простой вид экрана Upshot показан на рис. 2.2. Результат представлен в виде полос, по одной полосе на каждый процесс. Каждая полоса состоит из участков разного цвета (для чернобелых мониторов цвет заменяется различными штриховками). Каждому цвету соответствует состояние процесса определенного типа. Внизу приведены отметки времени, начинающиеся от нуля. Такое представление позволяет визуально определить состояние любого процесса в любой момент времени.
Рис. 2.2. Представление результатов профилирования с помощью upshot
Существуют и более сложные изображения окон, которые позволяют менять размер изображения по горизонтали или вертикали, центрировать на любой точке дисплея, выбранной мышью.
Jumpshot-2 и Jumpshot-3. Существует еще две версии, поставляемых вместе с MPE. Это Jumpshot-2 и Jumpshot-3, развившиеся из Upshot и Nupshot. Обе написаны на Java и являются графическими средствами визуализации для интерпретации двоичных файлов трасс, которые показывают их на дисплее.
Конкретные сведения по средствам просмотра обычно представлены в соответствующей реализации MPICH.
КОНТРОЛЬНЫЕ ВОПРОСЫ И ЗАДАНИЯ К ГЛАВЕ 2
Контрольные вопросы к 2.1
1.Что такое реализация MPI?
2.Что такое MPICH?
3.Укажите основные функции MPICH.
4.Дайте определение интерфейса абстрактного прибора ADI.
43
5.Какие типы ADI известны?
6.Что такое канальный интерфейс?
7.Что такое прямая реализация MPICH?
8.Какие протоколы используются для обмена сообщениями между процессами?
Контрольные вопросы к 2.2
1.Как производится запуск с помощью команды MPIRun?
2.Как задается число процессов при запуске с MPIRun?
3.Что выполняет опция –localonly?
4.Для чего используется процедура MPIConfig?
5.Для чего используется команда MPIRegister?
Контрольные вопросы к 2.3
1.Что такое библиотека MPE, ее назначение?
2.Основные функции MPE?
3.Что такое профилирование?
4.Какова методика оценки эффективности вычислений?
5.Что такое регистрация, логфайлы?
6.Как создается файл регистрации?
7.Какие процедуры используются при создании логфайлов?
8.Опишите процесс создания логфайлов на примере программы вычисления числа π.
Контрольные вопросы к 2.4
1.Какие способы анализа логфайлов Вы знаете?
2.Какое различие между форматами логфайлов ALOG, CLOG и SLOG?
3.Какие средства просмотра логфайлов графического типа Вы знаете?
4.Объясните структуру изображения, создаваемого инструментом upshot?
44

Р А З Д Е Л 2. БИБЛИОТЕКА ФУНКЦИЙ MPI
Глава 3. ПАРНЫЕ МЕЖПРОЦЕССНЫЕ ОБМЕНЫ
3.1. ВВЕДЕНИЕ
Главы 3 − 6 написаны в соответствии со стандартом MPI-1.2 [20, 11], также использовались книги [4, 5, 6,7] и другие документы.
Передача и прием сообщений процессами – это базовый коммуникационный механизм MPI. Основными операциями парного обмена являются операции send (послать) и receive (получить). Их использование иллюстрируется следующим примером:
#include "mpi.h" main( argc, argv ) 7 int argc;
char **argv;
{char message[20]; int myrank; MPI_Status status;
MPI_Init( &argc, &argv );
MPI_Comm_rank( MPI_COMM_WORLD, &myrank );
if (myrank == 0) |
/* код для процесса 0 */ |
{strcpy(message,"Hello, there");
MPI_Send(message,strlen(message),MPI_CHAR,1,99, MPI_COMM_WORLD);
}
else /* код для процесса 1 */
{ MPI_Recv(message, 20, MPI_CHAR, 0, 99, MPI_COMM_WORLD, &status);
printf("received :%s:\n", message);
}
MPI_Finalize();
}
В этом примере процесс с номером 0 (myrank = 0) посылает сообщение процессу с номером 1, используя операцию посылки MPI_Send. Эта операция описывает буфер посылающего процесса, из которого извлекаются посылаемые данные. В приведенном примере посылающий буфер состоит из накопителя в памяти процесса 0, содержащего переменную message. Размещение, размер и тип буфера
45
посылающего процесса описываются первыми тремя параметрами операции send. Посланное сообщение будет содержать 13 символов этой переменной. Операция посылки также связывает с сообщением его атрибуты. Атрибуты определяют номер процесса-получателя сообщения и содержат различную информацию, которая может быть использована операцией receive, чтобы выбрать определенное сообщение среди других. Последние три параметра операции посылки описывают атрибуты посланного сообщения. Процесс 1 (myrank = 1) получает это сообщение, используя операцию приема MPI_Recv, и данные сообщения записываются в буфер процесса-получателя. В приведенном примере буфер получателя состоит из накопителя в памяти процесса один, содержащего строку message. Первые три параметра операции приема описывают размещение, размер и тип буфера приема. Следующие три параметра необходимы для выбора входного сообщения. Последний параметр необходим для возврата информации
отолько что полученном сообщении.
3.2.ОПЕРАЦИИ БЛОКИРУЮЩЕЙ ПЕРЕДАЧИ
ИБЛОКИРУЮЩЕГО ПРИЕМА
|
|
3.2.1. Блокирующая передача |
MPI_SEND(buf, count, datatype, dest, tag, comm) |
||
IN |
buf |
начальный адрес буфера посылки сообщения (альтернатива) |
IN |
count |
число элементов в буфере посылки (неотрицательное целое) |
IN |
datatype |
тип данных каждого элемента в буфере передачи (дескриптор) |
IN |
dest |
номер процесса-получателя (целое) |
IN |
tag |
тэг сообщения (целое) |
IN |
comm |
коммуникатор (дескриптор) |
int MPI_Send (void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
MPI_SEND(BUF, COUNT, DATATYPE, DEST, TAG, COMM, IERROR) <type> BUF(*)
INTEGER COUNT, DATATYPE, DEST, TAG, COMM, IERROR
void MPI::Comm::Send (const void* buf, int count, const MPI::Datatype& datatype, int dest, int tag) const
Семантика этого блокирующего вызова описана в 3.4.
46
3.2.2. Данные в сообщении
Буфер посылки описывается операцией MPI_SEND, в которой указано количество последовательных элементов, тип которых указан в поле datatype, начиная с элемента по адресу buf. Длина сообщения задается числом элементов, а не числом байт.
Число данных count в сообщении может быть равно нулю, это означает, что область данных в сообщении пуста. Базисные типы данных в сообщении соответствуют базисным типам данных используемого языка программирования. Список возможного соответствия этих типов данных для языка Fortran и MPI представлен ниже.
MPI datatype |
Fortran datatype |
MPI_INTEGER |
INTEGER |
MPI_REAL |
REAL |
MPI_DOUBLE_PRECISION |
DOUBLE PRECISION |
MPI_COMPLEX |
COMPLEX |
MPI_LOGICAL |
LOGICAL |
MPI_CHARACTER |
CHARACTER(1) |
MPI_BYTE |
|
MPI_PACKED |
|
Список соответствия типов данных для языка С и MPI дан ниже.
MPI datatype |
C datatype |
MPI_CHAR |
signed char |
MPI_SHORT |
signed short int |
MPI_INT |
signed int |
MPI_LONG |
signed long int |
MPI_UNSIGNED_CHAR |
unsigned char |
MPI_UNSIGNED_SHORT |
unsigned short int |
MPI_UNSIGNED |
unsigned int |
MPI_UNSIGNED_LONG |
unsigned long int |
MPI_FLOAT |
float |
MPI_DOUBLE |
double |
MPI_LONG_DOUBLE |
long double |
MPI_BYTE |
|
MPI_PACKED |
|
Типы MPI_BYTE и MPI_PACKED не имеют соответствия в языках С или Fortran. Значением типа MPI_BYTE является байт. Байт не интерпретируется и отличен от символа. Различные машины могут иметь различное представление для символов или могут использовать
47
для представления символов более одного байта. С другой стороны, байт имеет то же самое двоичное значение на всех машинах.
3.2.3.Атрибуты сообщения
Вдополнение к описанию данных сообщение несет информацию, которая используется, чтобы различать и выбирать сообщения. Эта информация состоит из фиксированного количества полей, которые в совокупности называются атрибутами сообщения. Эти поля таковы: source, destination, tag, communicator (номер процесса-отправителя сообщения, номер процесса-получателя, тэг, коммуникатор).
Целочисленный аргумент тэг используется, чтобы различать типы сообщений. Диапазон значений тэга находится в пределах 0,…,UB, где верхнее значение UB зависит от реализации. MPI требует, чтобы UB было не менее 32767.
Аргумент comm описывает коммуникатор, который используется
воперации обмена. Коммуникатор описывает коммуникационный контекст коммуникационной операции. Сообщение всегда принимается внутри контекста, в котором оно было послано; сообщения, посланные в различных контекстах, не взаимодействуют.
Коммуникатор также описывает ряд процессов, которые разделяют этот коммуникационный контекст. Эта группа процессов упорядочена, и процессы определяются их номером внутри этой группы: диапазон значений для dest есть 0,...,n-1, где n есть число процессов в группе
ВMPI предопределен коммуникатор MPI_COMM_WORLD. Он разрешает обмен для всех процессов, которые доступны после инициализации MPI, и процессы идентифицируются их номерами в груп-
пе MPI_COMM_WORLD.
3.2.4.Блокирующий прием
MPI_RECV (buf, count, datatype, source, tag, comm, status)
OUT |
buf |
начальный адрес буфера процесса-получателя (альтернатива) |
IN |
count |
число элементов в принимаемом сообщении (целое) |
IN |
datatype |
тип данных каждого элемента сообщения (дескриптор) |
IN |
source |
номер процесса-отправителя (целое) |
IN |
tag |
тэг сообщения (целое) |
IN |
comm |
коммуникатор (дескриптор) |
OUT |
status |
параметры принятого сообщения (статус) |
int MPI_Recv (void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)
48
MPI_RECV(BUF, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
<type> BUF(*)
INTEGER COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS(MPI_STATUS_SIZE), IERROR
void MPI::Comm::Recv (void* buf, int count, const MPI::Datatype& datatype, int source, int tag) const
Буфер получения состоит из накопителя, содержащего последовательность элементов, размещенных по адресу buf.
Тип элементов указан в поле datatype. Длина получаемого сообщения должна быть равна или меньше длины буфера получения, в противном случае будет иметь место ошибка переполнения. Если сообщение меньше размера буфера получения, то в нем модифицируются только ячейки, соответствующие длине сообщения.
Прием сообщения осуществляется, если его атрибуты соответствуют значениям источника, тэга и коммуникатора, которые указаны в операции приема. Процесс-получатель может задавать значение MPI_ANY_SOURCE для отправителя и/или значение MPI_ANY_TAG для тэга, определяя, что любой отправитель и/или тэг разрешен. Нельзя задать произвольное значение для comm. Следовательно, сообщение может быть принято, если оно адресовано данному получателю и имеет соответствующий коммуникатор.
Тэг сообщения задается аргументом tag операции приема. Аргумент отправителя, если он отличен от MPI_ANY_SOURCE, задается как номер внутри группы процессов, связанной с тем же самым коммуникатором. Следовательно, диапазон значений для аргумента от-
правителя есть {0,...,n-1}U{MPI_ANY_SOURCE}, где n есть количе-
ство процессов в этой группе.
Отметим ассиметрию между операциями посылки и приема. Операция приема допускает получение сообщения от произвольного отправителя, в то время как в операции посылки должен быть указан уникальный получатель.
Допускается ситуация, когда имена источника и получателя совпадают, то есть процесс может посылать сообщение самому себе (это небезопасно, поскольку может привести к дедлоку (deadlock)).
49
3.2.5. Возвращаемая статусная информация
Источник или тэг принимаемого сообщения могут быть неизвестны, если в операции приема были использованы значения типа ANY.
Иногда может потребоваться возвратить различные коды ошибок для каждого запроса. Эта информация возвращается с помощью аргу-
мента status операции MPI_RECV.
Тип аргумента status определяется MPI. Статусные переменные размещаются пользователем явно, то есть они не являются системными объектами.
Вязыке С status есть структура, которая содержит три поля, назы-
ваемые MPI_SOURCE, MPI_TAG и MPI_ERROR. Следовательно, status.MPI_SOURCE, status.MPI_TAG и status.MPI_ERROR со-
держат источник, тэг и код ошибки принятого сообщения.
Вязыке Fortran status есть массив целых значений размера
MPI_STATUS_SIZE. Константы MPI_SOURCE, MPI_TAG и MPI_ERROR определяют объекты, которые хранят поля источника, тэга и ошибки. Следовательно, status(MPI_SOURCE), status(MPI_TAG) и status(MPI_ERROR) содержат соответственно источник, тэг и код ошибки принимаемого сообщения.
Вызовы передачи сообщений не модифицируют значения полей кода ошибки статусных переменных. Статусный аргумент также возвращает информацию о длине принятого сообщения. Эта информация не является доступной непосредственно, как поле статусной переменной, и требуется вызов MPI_GET_COUNT, чтобы «декодировать» эту информацию.
MPI_GET_COUNT(status, datatype, count)
IN |
status |
статус операции приема (статус ) |
IN |
datatype тип данных каждого элемента приемного буфера (дескриптор) |
|
OUT |
count |
количество полученных единиц (целое) |
int MPI_Get_count (MPI_Status *status,MPI_Datatype datatype, int *count)
MPI_GET_COUNT(STATUS, DATATYPE, COUNT, IERROR)
INTEGER STATUS(MPI_STATUS_SIZE), DATATYPE, COUNT, IERROR int Status :: Get_count (const MPI :: Datatype& datatype) const
Операция MPI_GET_COUNT возвращает число полученных элементов. Аргумент datatype следует сопоставлять с аргументом из операции приема, которая устанавливает статусную переменную.
50