Чтобы отправить один элемент этой структуры, просто proceed as usual путем создания структурированного типа данных с использованием MPI_TYPE_CREATE_STRUCT
. В зависимости от того, как куча и стек программы расположены друг относительно друга, смещение B(1)
относительно N
может стать огромным положительным или отрицательным числом, но это не проблема на большинстве платформ Unix, а число должен соответствовать диапазону INTEGER(KIND=MPI_ADDRESS_KIND)
.
Важно: Отдельные экземпляры структуры будут скорее всего имеют разные смещения B
относительно N
, поэтому тип данных MPI может быть использован только для отправки конкретной записи, которая была использована для получения зачетов во время строительства тип данных.
Когда я пытаюсь использовать MPI_TYPE_CREATE_STRUCT создать производный тип данных для такого Struct, случается, что диффере процессоры создают несовместимые производные типы данных. Это связано с тем, что Struct% B (:) может находиться в разных ячейках памяти относительно первого элемента Struct% N на разных ЦП.
Это не проблема. Типы данных MPI с обеих сторон операции обмена данными должны быть только конгруэнтными, что означает, что они должны состоять из одних и тех же базовых типов данных в одной и той же последовательности. Смещение каждого элемента не имеет значения. Иными словами, до тех пор, пока как отправитель, так и получатель указывают те же типы и количество элементов данных в вызове MPI_TYPE_CREATE_STRUCT
, программа будет работать правильно.
Чтобы отправить несколько элементов, все становится немного сложнее. Существует два решения:
Используйте MPI_PACK
для сериализации данных со стороны отправителя и MPI_UNPACK
для десериализации его на стороне приемника. Поскольку для упаковки и распаковки требуется дополнительное пространство для буфера, это удваивает требования к памяти программы.
или
Создайте отдельную структуру MPI тип данных для каждой записи, а затем создать структуру типа данных, который сочетает в себе все записи.Вот пример того, как отправить массив из двух таких структур, один с 10 элементов в B
и один с 20:
TYPE(Struct) :: Structs(2)
ALLOCATE(Structs(1)%B(10))
ALLOCATE(Structs(2)%B(20))
! (1) Create a separate structure datatype for each record
DO i=1,2
CALL MPI_GET_ADDRESS(Structs(i)%N, POS_(1), IError)
CALL MPI_GET_ADDRESS(Structs(i)%A, POS_(2), IError)
CALL MPI_GET_ADDRESS(Structs(i)%B(1), POS_(3), IError)
Offsets = POS_ - POS_(1)
Types(1) = MPI_INTEGER
Types(2) = MPI_REAL8
Types(3) = MPI_REAL8
Blocks(1) = 1
Blocks(2) = 1
Blocks(3) = i * 10
CALL MPI_TYPE_CREATE_STRUCT(3, Blocks, Offsets, Types, Elem_Type(i), IError)
END DO
! (2) Create a structure of structures that describes the whole array
CALL MPI_GET_ADDRESS(Structs(1)%N, POS_(1), IError)
CALL MPI_GET_ADDRESS(Structs(2)%N, POS_(2), IError)
Offsets = POS_ - POS_(1)
Types(1) = Elem_Type(1)
Types(2) = Elem_Type(2)
Blocks(1) = 1
Blocks(2) = 1
CALL MPI_TYPE_CREATE_STRUCT(2, Blocks, Offsets, Types, TwoElem_Type, IError)
CALL MPI_TYPE_COMMIT(TwoElem_Type, IError)
! (2.1) Free the intermediate datatypes
DO i=1,2
CALL MPI_TYPE_FREE(Elem_Type(i), IError)
END DO
! (3) Send the array
CALL MPI_SEND(Structs(1)%N, 1, TwoElem_Type, ...)
Обратите внимание, что хотя строительство MPI типов данных является относительно дешевой операцией, вы не должны использовать описанную выше процедуру для отправки, например, 1000000 экземпляров структурированного типа. Кроме того, дескрипторы типа MPI живут в памяти, управляемой библиотекой, и важно своевременное освобождение типов данных, которые больше не нужны.
Очень странно, как вы написали весь этот вопрос, и нигде вы не указали Fortran, язык, который вы используете. Хорошо, я пометил это для вас. –
Вы видели http://stackoverflow.com/questions/2258759/passing-variable-length-structures-between-mpi-processes и http://stackoverflow.com/questions/4273253/variable-sized-message-in- mpi? –
Извините за флаг ... Я видел эти ссылки всего лишь минуту назад, они не решают проблему, с которой я столкнулся, что я имею в виду: использовать REAL * 8 :: B (2) вместо allocatable один в порядке и без проблем! Проблема показывает, когда я использую REAL * 8, ALLOCATABLE :: B (:) @JohnZwinck –