|
Производные типы и упаковка данных
Использование простейших производных типов
MPI4Type1°. В главном процессе дана K − 1 тройка целых чисел, где K — количество процессов. Используя производный тип, содержащий три целых числа, и одну коллективную операцию пересылки данных, переслать все данные из главного процесса в подчиненные и вывести их в подчиненных процессах в том же порядке.
MPI4Type2°. В главном процессе дана K − 1 тройка целых чисел, где K — количество процессов. Используя производный тип, содержащий три целых числа, и одну коллективную операцию пересылки данных, переслать по одной тройке чисел в каждый из подчиненных процессов и вывести их в подчиненных процессах в том же порядке.
MPI4Type3°. В каждом подчиненном процессе дана тройка целых чисел. Используя производный тип, содержащий три целых числа, и одну коллективную операцию пересылки данных, переслать числа из подчиненных процессов в главный и вывести полученные числа в порядке возрастания рангов переславших их процессов.
MPI4Type4°. В главном процессе дана K − 1 тройка чисел, где K — количество процессов, причем первые два числа каждой тройки являются целыми, а третье число — вещественным. Используя производный тип, содержащий три числа (два целых и одно вещественное), переслать числа из главного процесса в подчиненные и вывести их в подчиненных процессах в том же порядке.
MPI4Type5°. В главном процессе дана K − 1 тройка чисел, где K — количество процессов, причем первое и третье число каждой тройки являются целыми, а второе число — вещественным. Используя производный тип, содержащий три числа (целое, вещественное, целое), переслать по одной тройке чисел в каждый из подчиненных процессов и вывести их в подчиненных процессах в том же порядке.
MPI4Type6°. В каждом подчиненном процессе даны три числа: одно вещественное и два целых. Используя производный тип, содержащий три числа (одно вещественное и два целых), переслать числа из подчиненных процессов в главный и вывести полученные числа в порядке возрастания рангов переславших их процессов.
MPI4Type7°. В каждом процессе даны три числа: первое и третье являются целыми, а второе — вещественным. Используя производный тип, содержащий три числа (целое, вещественное, целое), переслать данные из каждого процесса во все процессы и вывести в каждом процессе полученные числа в порядке возрастания рангов переславших их процессов (включая числа, полученные из этого же процесса).
MPI4Type8°. В каждом подчиненном процессе даны R троек чисел, где R — ранг процесса. Два первых числа в каждой тройке являются целыми, а последнее — вещественным. Используя производный тип, содержащий три числа (два целых и одно вещественное), переслать числа из подчиненных процессов в главный и вывести полученные числа в порядке возрастания рангов переславших их процессов.
Пересылка упакованных данных
MPI4Type9°. В главном процессе даны два набора: первый содержит K целых, а второй K вещественных чисел, где K — количество процессов. Используя функции упаковки MPI_Pack и MPI_Unpack и одну коллективную операцию пересылки данных, переслать все данные из главного процесса в подчиненные и вывести их в подчиненных процессах в том же порядке.
MPI4Type10°. В главном процессе дана K − 1 тройка чисел, где K — количество процессов, причем первое и третье число каждой тройки является целым, а второе число — вещественным. Используя функции упаковки и одну коллективную операцию пересылки данных, переслать по одной тройке чисел в подчиненные процессы и вывести их в подчиненных процессах в том же порядке.
MPI4Type11°. В главном процессе дана K − 1 тройка чисел, где K — количество процессов, причем первые два числа каждой тройки являются целыми, а третье число — вещественным. Используя функции упаковки и одну коллективную операцию пересылки данных, переслать все данные из главного процесса в подчиненные и вывести их в подчиненных процессах в том же порядке.
MPI4Type12°. В каждом подчиненном процессе даны три числа: два целых и одно вещественное. Используя функции упаковки и одну коллективную операцию пересылки данных, переслать числа из подчиненных процессов в главный и вывести полученные числа в порядке возрастания рангов переславших их процессов.
MPI4Type13°. В каждом подчиненном процессе дан набор из одного вещественного и R целых чисел, где значение R равно рангу процесса (в процессе 1 дано одно целое число, в процессе 2 — два целых числа, и т. д.). Используя функции упаковки и одну функцию передачи и приема, переслать все данные в главный процесс и вывести эти данные в порядке возрастания рангов переславших их процессов.
Более сложные виды производных типов
MPI4Type14°. В главном процессе даны два набора целых чисел: A размера 3K и N размера K, где K — количество подчиненных процессов. Считая, что элементы наборов нумеруются от 1, переслать и вывести в каждом подчиненном процессе ранга R (R = 1, 2, …, K) NR элементов из набора A, начиная с элемента AR и перебирая их через один (например, если N2 равно 3, то в процесс ранга 2 надо переслать элементы A2, A4, A6). Использовать для пересылки каждого набора элементов по одному вызову функций MPI_Send, MPI_Probe и MPI_Recv, причем функция MPI_Recv должна возвращать массив, содержащий только те элементы, которые требуется вывести. Для этого в главном процессе определить новый тип, содержащий единственный целочисленный элемент и дополнительный конечный пустой промежуток, равный размеру элемента целого типа. Использовать в функции MPI_Send исходный массив A с требуемым смещением, указав в качестве второго параметра количество элементов, равное NR, а в качестве третьего параметра — новый тип. В функции MPI_Recv использовать целочисленный массив размера NR и тип MPI_INT. Для определения количества NR переданных элементов использовать в подчиненных процессах функцию MPI_Get_count. Указание. Для задания завершающего пустого промежутка при определении нового типа в MPI-2 следует использовать функцию MPI_Type_create_resized (в данном случае эту функцию надо применить к типу MPI_INT). В MPI-1 надо использовать метку нулевого размера типа MPI_UB совместно с функцией MPI_Type_struct (в стандарте MPI-2 тип MPI_UB объявлен устаревшим).
MPI4Type15°. В главном процессе дана вещественная квадратная матрица порядка K, где K — количество подчиненных процессов (матрица должна храниться в одномерном массиве A, в котором элементы матрицы располагаются по строкам). Считая, что столбцы матрицы нумеруются от 1, переслать и вывести в каждом подчиненном процессе ранга R (R = 1, 2, …, K) элементы столбца матрицы с номером R. Использовать по одному вызову функций MPI_Send и MPI_Recv, причем функция MPI_Recv должна возвращать массив, содержащий только те элементы, которые требуется вывести. Для этого в главном процессе определить новый тип, содержащий единственный вещественный элемент и дополнительный конечный пустой промежуток требуемого размера. Использовать в функции MPI_Send массив A с требуемым смещением, указав в качестве второго параметра число K (т. е. количество элементов в каждом столбце), а в качестве третьего параметра — новый тип. В функции MPI_Recv использовать вещественный массив размера K и тип MPI_DOUBLE. Указание. См. указание к задаче MPI4Type14.
MPI4Type16°. В каждом из подчиненных процессов дан столбец вещественной квадратной матрицы порядка K, где K — количество подчиненных процессов, причем в процессе ранга R (R = 1, …, K) содержится столбец с номером R, если считать, что столбцы нумеруются от 1. Переслать все столбцы матрицы в главный процесс, разместив их в одномерном массиве A, в котором элементы матрицы хранятся по строкам, и вывести полученный массив A. Для пересылки каждого столбца использовать по одному вызову функций MPI_Send и MPI_Recv, причем функция MPI_Recv должна в качестве первого параметра содержать массив A (с требуемым смещением), а в качестве второго параметра — число 1. Для этого в главном процессе определить новый тип, содержащий K вещественных элементов, после каждого из которых следует пустой промежуток требуемого размера. Определение нового типа провести в два этапа: на первом создать вспомогательный тип, состоящий из одного вещественного числа и требуемого конечного пустого промежутка (см. указание к MPI4Type14), на втором — создать на его основе итоговый тип с помощью функции MPI_Type_contiguous, который использовать в качестве третьего параметра функции MPI_Recv (функцию MPI_Type_commit достаточно вызвать только для итогового типа). В функции MPI_Send использовать вещественный массив размера K и тип MPI_DOUBLE.
MPI4Type17°. Количество подчиненных процессов K кратно 3 и не превосходит 9. В каждом процессе дано целое число N; все числа N одинаковы и лежат в диапазоне от 3 до 5. Кроме того, в каждом подчиненном процессе дана целочисленная квадратная матрица порядка N (блок), которую следует прочесть в одномерный массив B по строкам. Переслать все массивы B в главный процесс и составить из них блочную матрицу размера (K/3) × 3 (размер указан в блоках), располагая блоки по строкам (первая строка блоков должна содержать блоки, полученные из процессов ранга 1, 2, 3, вторая — из процессов ранга 4, 5, 6, и т. д.). Блочная матрица должна храниться по строкам в одномерном массиве A. Использовать для пересылки каждого блока B по одному вызову функций MPI_Send и MPI_Recv, причем функция MPI_Recv должна в качестве первого параметра содержать массив A (с требуемым смещением), а в качестве второго параметра — число 1. Для этого в главном процессе определить новый тип, содержащий N наборов элементов, причем каждый набор содержит N целых чисел, а между наборами располагается пустой промежуток требуемого размера (при определении нового типа использовать функцию MPI_Type_vector). Указать созданный тип в качестве третьего параметра функции MPI_Recv. В функции MPI_Send использовать целочисленный массив B (размера N·N) и тип MPI_INT.
MPI4Type18°. Количество подчиненных процессов K кратно 3 и не превосходит 9. В главном процессе дано целое число N, лежащее в диапазоне от 3 до 5, и целочисленная блочная матрица порядка (K/3) × 3 (размер указан в блоках). Каждый блок представляет собой нижнетреугольную квадратную матрицу порядка N и содержит все элементы этой матрицы (в том числе и нулевые). Блочную матрицу следует прочесть в одномерный массив A по строкам. Переслать в каждый подчиненный процесс ненулевую часть соответствующего блока исходной матрицы, перебирая блоки по строкам (блоки из первой строки должны пересылаться в процессы ранга 1, 2, 3, блоки из второй строки — в процессы ранга 4, 5, 6, и т. д.), и вывести в каждом подчиненном процессе полученные данные (по строкам). Использовать для пересылки каждого блока по одному вызову функций MPI_Send, MPI_Probe и MPI_Recv, причем функция MPI_Send должна в качестве первого параметра содержать массив A (с требуемым смещением), а в качестве второго параметра — число 1. Для этого в главном процессе определить новый тип, содержащий N наборов элементов, причем каждый набор содержит ненулевую часть очередной строки блока (первый набор состоит из одного элемента, второй из двух, и т. д.), а между наборами располагается пустой промежуток требуемого размера (при определении нового типа использовать функцию MPI_Type_indexed). Указать созданный тип в качестве третьего параметра функции MPI_Send. В функции MPI_Recv использовать целочисленный массив B (содержащий ненулевую часть полученного блока) и тип MPI_INT. Для определения количества переданных элементов использовать в подчиненных процессах функцию MPI_Get_count.
MPI4Type19°. Количество подчиненных процессов K кратно 3 и не превосходит 9. В каждом процессе дано целое число N; все числа N одинаковы и лежат в диапазоне от 3 до 5. Кроме того, в каждом подчиненном процессе дано целое число P и ненулевые элементы целочисленной квадратной матрицы порядка N (Z-блока), которую следует прочесть в одномерный массив B по строкам. Ненулевые элементы располагаются в Z-блоке в форме символа «Z», т. е. занимают первую и последнюю строку, а также побочную диагональ. Определить в главном процессе нулевую целочисленную прямоугольную матрицу размера N·(K/3) × 3N, создав для этого одномерный массив A и обнулив его элементы (которые должны храниться в массиве A по строкам). Перебирая подчиненные процессы в порядке возрастания их рангов, переслать из каждого подчиненного процесса данную в нем ненулевую часть Z-блока и записать полученный блок в массив A, начиная с элемента массива A с индексом P (позиции Z-блоков могут перекрываться; в этом случае элементы блоков, полученных из процессов большего ранга, будут заменять некоторые из элементов ранее записанных блоков). Использовать для пересылки ненулевой части каждого Z-блока по одному вызову функций MPI_Send и MPI_Recv, причем функция MPI_Recv должна в качестве первого параметра содержать массив A (с требуемым смещением), а в качестве второго параметра — число 1. Для этого в главном процессе определить новый тип, содержащий N наборов элементов, причем первый и последний набор содержат по N целых чисел, остальные наборы — по одному числу, а между наборами располагается пустой промежуток требуемого размера (при определении нового типа использовать функцию MPI_Type_indexed). Указать созданный тип в качестве третьего параметра функции MPI_Recv. В функции MPI_Send использовать целочисленный массив B, содержащий ненулевую часть Z-блока (по строкам), и тип MPI_INT. Указание. Для передачи в главный процесс позиции P вставки Z-блока используйте параметр msgtag; для этого в подчиненных процессах задавайте значение P в качестве параметра msgtag функции MPI_Send, а в главном процессе до вызова функции MPI_Recv вызывайте функцию MPI_Probe с параметром MPI_ANY_TAG и анализируйте возвращенный ею параметр типа MPI_Status.
MPI4Type20°. Количество подчиненных процессов K кратно 3 и не превосходит 9. В каждом процессе дано целое число N; все числа N одинаковы и лежат в диапазоне от 3 до 5. Кроме того, в каждом подчиненном процессе дано целое число P и ненулевые элементы целочисленной квадратной матрицы порядка N (U-блока), которую следует прочесть в одномерный массив B по строкам. Ненулевые элементы располагаются в U-блоке в форме символа «U», т. е. занимают первый и последний столбец, а также последнюю строку. Определить в главном процессе нулевую целочисленную прямоугольную матрицу размера N·(K/3) × 3N, создав для этого одномерный массив A и обнулив его элементы (которые должны храниться в массиве A по строкам). Перебирая подчиненные процессы в порядке возрастания их рангов, переслать из каждого подчиненного процесса данную в нем ненулевую часть U-блока и записать полученный блок в массив A, начиная с элемента массива A с индексом P (позиции U-блоков могут перекрываться; в этом случае элементы блоков, полученных из процессов большего ранга, будут заменять некоторые из элементов ранее записанных блоков). Использовать для пересылки ненулевой части каждого U-блока по одному вызову функций MPI_Send и MPI_Recv, причем функция MPI_Recv должна в качестве первого параметра содержать массив A (с требуемым смещением), а в качестве второго параметра — число 1. Для этого в главном процессе определить новый тип, содержащий требуемое количество наборов элементов с пустыми промежутками между ними (при определении нового типа использовать функцию MPI_Type_indexed). Указать созданный тип в качестве третьего параметра функции MPI_Recv. В функции MPI_Send использовать целочисленный массив B, содержащий ненулевую часть U-блока (по строкам), и тип MPI_INT. Указание. См. указание к задаче MPI4Type19.
Коллективная функция MPI_Alltoallw (MPI-2)
MPI4Type21°. Решить задачу MPI4Type15, используя для пересылки данных вместо функций MPI_Send и MPI_Recv одну коллективную операцию. Указание. Использовать функции группы Scatter не удастся, так как значения смещений для рассылаемых элементов (столбцов матрицы) требуется указывать не в элементах, а в байтах. Поэтому подходящим вариантом будет введенная в MPI-2 функция MPI_Alltoallw, позволяющая наиболее гибким образом настраивать вариант коллективной пересылки. В данном случае с ее помощью следует реализовать вариант рассылки вида Scatter (при этом большинство параметров-массивов, используемых в этой функции, необходимо по-разному определять в главном и подчиненных процессах). В стандарт MPI-3 включен неблокирующий вариант данной функции — MPI_Ialltoallw, имеющий те же особенности, что и другие неблокирующие коллективные функции (эти функции рассмотрены в соответствующей подгруппе группы MPI5Comm).
MPI4Type22°. Решить задачу MPI4Type16, используя для пересылки данных вместо функций MPI_Send и MPI_Recv одну коллективную операцию. Указание. См. указание к задаче MPI4Type21. В данном случае с помощью функции MPI_Alltoallw следует реализовать вариант рассылки вида Gather.
|