До сих пор все парные обмены использовали только непрерывные буферы, содержащие последовательности элементов одного типа. Это слишком большое ограничение по двум причинам. Часто необходимо передавать сообщения, которые содержат значения различных типов (например, целое число с последующим набором вещественных чисел); или нужно посылать несмежные данные (например, подблоки матрицы). Одно из решений состоит в том, чтобы упаковать несмежные данные в смежный буфер на стороне отправителя и распаковать обратно на приемной стороне. Недостаток состоит в том, что требуется дополнительная операция копирования память-память на обеих сторонах, даже когда коммуникационная подсистема имеет возможностиscatter-gather (разборки-сборки). Вместо этого MPI обеспечивает механизм для описания более общих буферов для несмежных коммуникаций, в которых используются производные типы данных, образуемые конструкторами, описанными в этом разделе. Этот метод конструирования производных типов данных может использоваться рекурсивно.
Универсальный тип данных (general datatype) есть скрытый объект, который описывается двумя составляющими:
При этом не требуется, чтобы смещения были положительными, различными или возрастающего порядка. Поэтому порядок объектов не обязан совпадать с их порядком в памяти, и объект может появляться более, чем один раз. Последовательность указанных выше пар называется картой типа (a type map). Последовательность базисных типов данных (смещения игнорируются) есть сигнатура типа.
Пусть
Typemap = { (type,disp), ..., (type, disp)} ,
является такой картой типа, где type есть базисные типы и disp есть смещения. Пусть
Typesig = { type, ... , type}
является связанной с типом сигнатурой. Карта типа вместе с адресом buf описывает коммуникационный буфер, который состоит из nэлементов, где i -ый элемент расположен по адресу buf + disp и имеет тип type. Сообщение, полученное из такого коммуникационного буфера, будет состоять из n значений с типами, определенными Typesig.
Можно использовать дескриптор общего типа данных как аргумент в операциях передачи или приема вместо аргумента базисного типа данных. Операция MPI_SEND (buf, 1, datatype,...) будет использовать буфер посылки, определенный адресом buf и общим типом данных, связанным с datatype; она будет генерировать сообщение с сигнатурой типа, определенной аргументом datatype. MPI_RECV(buf, 1, datatype,...) будет использовать приемный буфер, определенный базовым адресом buf и универсальный тип данных, связанный с datatype.
Универсальные типы данных могут использоваться во всех операциях приема и передачи. В разделе 3.12.5 будет обсужден случай, когда второй аргумент count имеет значение > 1.
Базисный тип данных, представленный в разделе 3.2.2 есть частный случай универсального типа и является предопределенным. Поэтому MPI_INT есть предопределенный указатель на тип данных с картой {(int, 0)} с одним элементом типа int и смещением нуль. Другие базисные типы подобны.
Экстент (extent) типа данных определяется как пространство, от первого байта до последнего байта, занятое элементами в этом типе данных, округленное вверх с учетом требований выравнивания данных. Это означает, что если
Typemap = { (type,disp), ..., (type, disp) } ,
то
lb(Typemap) = min (j) disp
extent(typemap) = ub(Typemap) - lb(Type map).
Если type требует выравнивания по байтовому адресу, то есть имеется множество k, тогда соответствует самому меньшему неотрицательному инкременту, необходимому, чтобы округлить extent(Typemap) до следующего множества из maxk. Полное определение extent дается в разделе 3.12.3.
Пример 3.19 Допустим, что Type = { (double, 0), (char, 8) } (double на смещении нуль с последующим char на смещении восемь). Предположим далее, что удвоенные значения должны быть выравнены по адресам, кратным восьми. Тогда экстент этого типа данных равен 16 (9 округлено к следующему значению, кратному 8). Тип данных, который состоит из знака, за которым сразу следует удвоенное значение, будет также иметь длину 16.
Объяснение: Определение экстента учитывает допущение, что сумма добавок на конце каждой структуры в массиве структур по крайней мере необходима для выполнения условий выравнивания. Более очевидное управление экстентом представлено в разделе 3.12.3. Такое явное управление необходимо в случаях, где допущение не выполняется, например, где используются объединенные типы (union types).[]