Пересылка разнотипных данных
Упаковка данных
Для пересылок разнородных данных наряду с созданием производных типов можно использовать операции упаковки и распаковки данных. Разнородные или расположенные не в последовательных ячейках памяти данные помещаются в один непрерывный буфер, пересылается, а потом полученное сообщение снова распределяется по нужным ячейкам памяти.
MPI_PACK(INBUF, INCOUNT, DATATYPE, OUTBUF, OUTSIZE, POSITION, COMM, IERR) <type> INBUF(*), OUTBUF(*) INTEGER INCOUNT, DATATYPE, OUTSIZE, POSITION, COMM, IERR
Упаковка INCOUNT элементов типа DATATYPE из массива INBUF в массив OUTBUF со сдвигом POSITION байт от начала массива. Буфер OUTBUF должен содержать по крайней мере OUTSIZE байт. После выполнения процедуры параметр POSITION увеличивается на число байт, равное размеру записи. Параметр сомм указывает на коммуникатор, в котором в дальнейшем будет пересылаться сообщение. Для пересылки упакованных данных используется тип данных MPI_PACKED.
MPI_UNPACK(INBUF, INSIZE, POSITION, OUTBUF, OUTCOUNT, DATATYPE, COMM, IERR) <type> INBUF(*), OUTBUF(*) INTEGER INSIZE, POSITION, OUTCOUNT, DATATYPE, COMM, IERR
Распаковка OUTCOUNT элементов типа DATATYPE из массива INBUF со сдвигом POSITION байт от начала массива в массив OUTBUF. Массив INBUF имеет размер не менее INSIZE байт.
MPI_PACK_SIZE(INCOUNT, DATATYPE, COMM, SIZE, IERR) INTEGER INCOUNT, DATATYPE, COMM, SIZE, IERR
Определение необходимого объема памяти SIZE (в байтах) для упаковки INCOUNT элементов типа DATATYPE. Необходимый для упаковки размер может превышать сумму размеров пакуемых элементов данных.
В следующем примере массив buf используется в качестве буфера для упаковки 10 элементов массива а типа real и 10 элементов массива b типа character. Полученное сообщение пересылается процедурой MPI_BCAST ОТ процесса о всем остальным процессам, полученное сообщение распаковывается при помощи вызовов процедур MPI_UNPACK.
program example2 0 include 'mpif.h' integer ierr, rank, position real a(10) character b(10), buf(100) call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) do i = 1, 10 a(i) = rank + 1.0 if(rank .eq. 0) then b(i) = 'a' else b(i) = 'b' end if end do position=0 if(rank .eq. 0) then call MPI_PACK(a, 10, MPI_REAL, buf, 100, position, & MPI_COMM_WORLD, ierr) call MPI_PACK(b, 10, MPI_CHARACTER, buf, 100, position, & MPI_COMM_WORLD, ierr) call MPI_BCAST(buf, 100, MPI_PACKED, 0, & MPI_COMM_WORLD, ierr) else call MPI_BCAST(buf, 100, MPI_PACKED, 0, & MPI_COMM_WORLD, ierr) position=0 call MPI UNPACK(buf, 100, position, a, 10, MPI_REAL, & MPI_COMM_WORLD, ierr) call MPI UNPACK(buf, 100, position, b, 10, & MPI_CHARACTER, MPI_COMM_WORLD, ierr) end if print *, 'procecc ', rank, ' a=', a, ' b=', b call MPI_FINALIZE(ierr) end
Задания
- Создать производный тип данных для пересылок диагональной матрицы.
Как соотносятся значения, возвращаемые процедурами MPI_TYPE_SIZE и MPI_TYPE_EXTENT?
- Можно ли использовать производные типы данных без вызова процедуры MPI_TYPE_COMMIT?
- Переслать нулевому процессу от всех процессов приложения структуру, состоящую из ранга процесса и названия узла, на котором данный процесс запущен (полученного с помощью процедуры MPI_GET_PROCESSOR_NAME ).
- Прямоугольная матрица распределена по процессам по строкам. Переставить строки матрицы в обратном порядке, используя для пересылок производный тип данных.
- Сделать предыдущую задачу с использованием пересылок упакованных данных.
- В чем преимущества и недостатки использования пересылок упакованных данных по сравнению с пересылками данных производных типов?
- Написать программу транспонирования матрицы с использованием производных типов данных.