Или вопрос можно перефразировать следующим образом: Зачем нужен тип данных с ненулевой нижней границей?Почему у нас есть нижняя и верхняя границы для типов данных в MPI?
Рассмотрим следующий пример:
struct S {
int a;
int b;
float c;
float d;
} array[N];
Если бы я был массив типа S[]
, и я хотел послать только значения полей b
и d
, я бы создать datatype
с типом карты { (4, MPI_INT), (12, MPI_FLOAT) }
. Во-первых, кажется, что такой тип может быть использован, чтобы правильно отправить массив struct S
:
MPI_Send(array, N, datatype, ...);
Но это не работает, если N > 1
. Такой тип имел бы lb = 4
, ub = 16
и extent = ub - lb = 12
. То есть, MPI будет считать, что второй элемент массива запускает 12 байтов из первого , что неверно.
Ну, это может быть не очень. В конце концов, как правило, для таких частично посланных структур мы есть указать точный размер структуры:
MPI_Type_create_resized(datatype, 0, sizeof(struct S), &resized);
Но я удивляюсь, почему мы всегда должны указать нулевой нижней границы. Зачем кому-то нужна ненулевая нижняя граница? Типы данных с ненулевыми нижними границами выглядят чрезвычайно запутанными для меня, и я не могу их понять.
Если бы я планировал создать систему типов для MPI, я бы описал тип с единственным параметром - его размером (протяженностью), который является шагом между двумя соседними элементами массива. Что касается MPI, я бы всегда задавал lb = 0
и extent = ub
. Такая система выглядит намного яснее для меня, и она будет работать правильно в описанном выше примере.
Но MPI выбрал другой способ. У нас есть два независимых параметров: нижний и верхние границы. Почему это так? Какая польза от этой дополнительной гибкости? Когда следует использовать типы данных с ненулевой нижней границей?
Извините, но ваш ответ на самом деле ничего не объясняет. 1) Я просмотрел стандарт и нашел несколько примеров с MPI_Type_create_resized. Однако ни один из примеров не использовал ненулевой фунт. 2) Я не понял вашу часть MPI_BOTTOM. Структура, которую вы описали, по своей сути является единственной в своем роде. У вас никогда не будет такого массива таких структур. Таким образом, для такого типа данных имеет значение только тип карты, в то время как границы вообще не имеют значения. 3) MPI_Type_create_subarray создает тип данных с lb = 0. – Nikolai
1) Примеры, приведенные в стандарте, не являются исчерпывающими. Допустимое использование типов с отрицательным LB предназначено для обработки массивов Fortran с отрицательными индексами, например. 'INTEGER A (-5: 5)'. 2) LB типа - это только минимальное смещение в типовой карте, если явный маркер LB не был помещен с использованием 'MPI_Type_create_resized'. MPI не используется для отправки только массивов. 3) Этот истинный LB типов данных, созданных с помощью 'MPI_Type_create_subarray', когда субарейк не начинается в начале массива, отличен от нуля. Он помещает явные привязанные маркеры, как и в вашем примере. –
Вы не * имеете * использовать '0' как LB в вызове' MPI_Type_create_resized'. Это вполне справедливо: 'MPI_Type_get_extent (тип данных, & lb, & extent); MPI_Type_create_resized (тип данных, lb, sizeof (struct S) и измененный размер); 'и' resized' будут иметь ненулевой LB и будут по-прежнему использоваться для отправки массивов 'struct S'. LB '0' используется для удобства, поскольку упрощает вычисление смещений в большинстве случаев при дальнейшем объединении типов данных. Это то, что делает конструктор subarray, и поэтому в типах данных их LB явно установлен в '0'. –