next up previous contents
Next: Преобразование данных Up: Соответствие типов данных и Previous: Соответствие типов данных и   Contents

Правила соответствия типов данных

Передача данных содержит следующие три фазы:

  1. Данные выталкиваются из буфера процесса-отправителя и части сообщения объединяются

  2. Сообщение передается от отправителя к получателю

  3. Данные выделяются из получаемого сообщения и помещаются в буфер получателя

Соответствие типов должно отслеживаться на каждой из трех фаз: тип каждой переменной в буфере посылки должен соответствовать типу, указанному для этого элемента в операции посылки; тип, описанный в операции посылки , должен соответствовать типу, указанному в операции приема; и тип каждой переменной в приемном буфере должен соответствовать типу, указанному для нее в операции приема. Программа, в которой не соблюдаются эти три правила, является неверной.

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

Типы отправителя и получателя (фаза два) соответствуют друг другу, если обе операции используют одинаковые названия. Это означает, что MPI_INTEGER соответствует MPI_INTEGER, MPI_REAL соответствует MPI_REAL, и так далее. Имеется одно исключение из этого правила, которое обсуждается в разделе 3.13, тип MPI_PACKED может соответствовать любому другому типу.

Тип переменной в хост (главной) программе соответствует типу, указанному в операции обмена, если название типа данных, используемое этой операцией, соответствует базисному типу переменной хост программы. Например, элемент с названием типа MPI_INTEGER соответствует в языке ФОРТРАН переменной типа INTEGER. Таблица, описывающая соответствие для языков ФОРТРАН и Си, представлена в разделе 3.2.2. Имеется два исключения из этого последнего правила: элемент с названием типа MPI_BYTE или MPI_PACKED может соответствовать любому байту памяти (на байт-адресуемой машине), без учета типа переменной, которая содержит этот байт. Тип MPI_PACKED используется для передачи данных, которые были явно упакованы, или для получения данных, которые будут явно распакованы (см. раздел 3.13). Тип MPI_BYTE позволяет передавать неизменным двоичное значение байта из памяти.

В итоге правила соответствия типов можно разделить на три категории, указанные ниже:

Следующие примеры иллюстрируют первые два случая.

Пример 3.1 Отправитель и получатель указывают типы соответствия.

CALL MPI_COMM_RANK(comm, rank, ierr) IF(rank.EQ.0) THEN CALL MPI_SEND(a(1), 10, MPI_REAL, 1, tag, comm, ierr) ELSE CALL MPI_RECV(b(1), 15, MPI_REAL, 0, tag, comm, status, ierr) END IF

Этот код корректен, если a и b есть действительные массивы размера $ \ge $ 10. (В языке ФОРТРАН может быть корректным использовать этот код даже если a или b имеют размер < 10, например, когда a(1) эквивалентно массиву с десятью действительными числами.)

Пример 3.2 Отправитель и получатель не указывают типы соответствия.

CALL MPI_COMM_RANK(comm, rank, ierr) IF(rank.EQ.0) THEN CALL MPI_SEND(a(1), 10, MPI_REAL, 1, tag, comm, ierr) ELSE CALL MPI_RECV(b(1), 40, MPI_BYTE, 0, tag, comm, status, ierr) END IF

Этот код неверен, поскольку отправитель и получатель описывают различные типы данных.

Пример 3.3 Отправитель и получатель описывают передачу нетипизированных значений.

CALL MPI_COMM_RANK(comm, rank, ierr) IF(rank.EQ.0) THEN CALL MPI_SEND(a(1), 40, MPI_BYTE, 1, tag, comm, ierr) ELSE CALL MPI_RECV(b(1), 60, MPI_BYTE, 0, tag, comm, status, ierr) END IF

Этот код правилен безотносительно к типу и размеру а и b (кроме случая, когда эти результаты выходят за границы памяти).

Совет пользователям: Если буфер типа MPI_BYTE передается в качестве аргумента операции MPI_SEND, то MPI будет посылать данные, хранимые в buf в смежных ячейках, начиная с адреса, указанного в аргументе buf. Это может иметь неожиданный результат, когда данные размещены не так, как предполагал их видеть пользователь. Например, некоторые компиляторы языка ФОРТРАН реализуют переменные типа CHARACTER как структуру, которая содержит длину знака и указатель на реальную строку. В такой среде передача и прием переменной CHARACTER с использованием типа MPI_BYTE не будет иметь ожидаемого результата передачи знаковой строки. По этой причине пользователю рекомендуется использовать типизированные обмены, где только возможно.[]

Тип MPI_CHARACTER соответствует одному знаку переменной языка ФОРТРАН с типом
CHARACTER, а не полной знаковой строке, хранимой в переменной. Переменные языка ФОРТРАН типа CHARACTER или подстроки передаются, как если бы они были массивами знаков. Это показано в примере ниже.

Пример 3.4 Передача знаков в языке ФОРТРАН

CHARACTER*10 a CHARACTER*10 b CALL MPI_COMM_RANK(comm, rank, ierr) IF(rank.EQ.0) THEN CALL MPI_SEND(a, 5, MPI_CHARACTER, 1, tag, comm, ierr) ELSE CALL MPI_RECV(b(6:10), 5, MPI_CHARACTER, 0, tag, comm, status, ierr) END IF

Последние пять знаков строки b в процессе 1 замещаются пятью первыми знаками строки процесса 0.

Объяснение: Альтернативой для MPI_CHARACTER могло бы быть соответствие знаку произвольной длины, однако это создает следующую проблему.

Знаковая переменная языка ФОРТРАН есть строка постоянной длины без специального символа конца. Не имеется зафиксированного соглашения о том, как представлять символы и как хранить их длину. Некоторые компиляторы передают аргумент знака процедуре как пару аргументов: один хранит адрес строки, другой - длину строки. Рассмотрим случай вызова обменаMPI, который передает коммуникационный буфер с типом derived datatype (производный тип данных, раздел 3.12). Если этот коммуникационный буфер содержит переменную типа MPI_CHARACTER, то информация о его длине не будет послана процедуре MPI.

Эта проблема приводит к заданию явной информации о длине знака в вызове MPI. Можно добавить параметр длины к типу MPI_CHARACTER, но это не добавляет удобства и те же возможности могут быть достигнуты определением подходящего производного типа данных.[]

Совет разработчикам: Некоторые компиляторы передают в языке ФОРТРАН аргумент типа
CHARACTER как структуру с длиной и указателем на реальную строку. В такой среде вызов MPI должен преобразовывать указатель, чтобы достичь строки.[]



Alex Otwagin 2002-12-10