Programming Taskbook


E-mail:

Пароль:

Регистрация пользователя   Восстановление пароля

English

ЮФУ SMBU

Электронный задачник по программированию

©  М. Э. Абрамян (Южный федеральный университет, Университет МГУ-ППИ в Шэньчжэне), 1998–2024

 

PT for MPI-2 | Группы заданий | MPI8Inter

PrevNext


Интеркоммуникаторы и динамическое создание процессов

Базовые возможности, связанные с созданием интеркоммуникаторов и их использованием для обмена сообщениями между отдельными процессами, определены в стандарте MPI-1. Поэтому 5 заданий данной группы можно выполнять с применением системы MPICH 1.2.5 (это задания MPI8Inter1–MPI8Inter4 и MPI8Inter9). Прочие задания посвящены новым возможностям по созданию интеркоммуникаторов (MPI8Inter5–MPI8Inter8), средствам коллективного обмена для интеркоммуникаторов (MPI8Inter10–MPI8Inter14) и использованию интеркоммуникаторов при динамическом создании процессов (MPI8Inter15–MPI8Inter22). Все эти возможности появились в стандарте MPI-2, поэтому для выполнения заданий необходимо подключать к программе систему MPICH2 1.3.

В качестве коммуникатора-посредника (третьего параметра peer функции MPI_Intercomm_create) следует указывать копию коммуникатора MPI_COMM_WORLD, созданную с помощью функции MPI_Comm_dup.

При динамическом создании процессов с помощью функции MPI_Comm_spawn в заданиях MPI8Inter15–MPI8Inter22 в качестве первого параметра command следует указывать имя исполняемого файла ptprj.exe, в качестве второго параметра argv достаточно указать константу NULL, в качестве четвертого параметра info — константу MPI_NULL_INFO, в качестве последнего параметра array_of_errcodes — константу MPI_ERRCODES_IGNORE. Если в задании не указано, какой коммуникатор должен использоваться в качестве исходного при создании новых процессов, то предполагается, что этим коммуникатором является MPI_COMM_WORLD.

Вместо строки «ptprj.exe» можно использовать реализованную в задачнике функцию char* GetExename(), которая возвращает полное имя исполняемого файла.

Создание интеркоммуникаторов

MPI8Inter1°. Количество процессов K — четное число. В каждом процессе дано целое число X. Используя функции MPI_Comm_group, MPI_Group_range_incl и MPI_Comm_create, создать коммуникаторы, первый из которых содержит процессы четного ранга в том же порядке (0, 2, …, K/2 − 2), а второй — процессы нечетного ранга в том же порядке (1, 3, …, K/2 − 1). Вывести ранги процессов R в созданных коммуникаторах. Затем объединить созданные коммуникаторы в интеркоммуникатор с помощью функции MPI_Intercomm_create. Используя функции MPI_Send и MPI_Recv для созданного интеркоммуникатора, получить для каждого процесса число X из процесса того же ранга, входящего в другую группу этого же интеркоммуникатора, и вывести полученные числа.

MPI8Inter2°. Количество процессов K — четное число. В каждом процессе дано целое число C и вещественное число X. Числа C равны либо 0, либо 1, количество значений 1 равно количеству значений 0, причем в процессе ранга 0 дано C, равное 0, а в процессе ранга K − 1 дано C, равное 1. Используя один вызов функции MPI_Comm_split, создать коммуникаторы, первый из которых содержит процессы со значениями C = 0 в том же порядке, а второй — процессы со значениями C = 1 в обратном порядке. Вывести ранги процессов R в созданных коммуникаторах (при этом значение R = 0 получат первый и последний процессы исходного коммуникатора MPI_COMM_WORLD). Затем объединить созданные коммуникаторы в интеркоммуникатор с помощью функции MPI_Intercomm_create. Используя функции MPI_Send и MPI_Recv для созданного интеркоммуникатора, получить для каждого процесса число X из процесса того же ранга, входящего в другую группу этого интеркоммуникатора, и вывести полученные числа.

MPI8Inter3°. Количество процессов K кратно 3. В процессах ранга 3N (N = 0, …, 3K − 3) дано вещественное число X, в процессах ранга 3N + 1 даны вещественные числа X и Y, в процессах ранга 3N + 2 дано вещественное число Y. Используя функции MPI_Comm_group, MPI_Group_range_incl и MPI_Comm_create, создать коммуникаторы, первый из которых содержит группу процессов ранга 3N в том же порядке (0, 3, …, K − 3), второй — группу процессов ранга 3N + 1 в обратном порядке (K − 2, K − 5, …, 1), а третий — группу процессов ранга 3N + 2 в том же порядке (2, 5, …, K − 1). Вывести ранги процессов R в созданных коммуникаторах. Затем, используя функцию MPI_Intercomm_create, объединить созданные коммуникаторы в два интеркоммуникатора: первый должен содержать первую и вторую группы процессов, а второй — вторую и третью группы. Используя функции MPI_Send и MPI_Recv для созданных интеркоммуникаторов, поменять числа X для процессов одинакового ранга, входящих в первую и вторую группу, и числа Y для процессов одинакового ранга, входящих во вторую и третью группу. Вывести в каждом процессе полученные числа.

Указание. Следует обратить внимание на то, что функция MPI_Intercomm_create должна вызываться один раз для процессов, входящих в первую и третью группы, и два раза для процессов, входящих во вторую группу, и такое же количество вызовов должно быть для функций MPI_Send и MPI_Recv.

MPI8Inter4°. Количество процессов K кратно 3. В каждом процессе даны три целых числа. Первое число (обозначаемое буквой C) лежит в диапазоне от 0 до 2, причем каждое из значений 0, 1, 2 встречается одинаковое число раз (равное K/3) и при этом в процессах ранга 0, 1, 2 значения C совпадают с рангами этих процессов. Используя один вызов функции MPI_Comm_split, создать коммуникаторы, первый из которых содержит процессы со значениями C = 0 в том же порядке, второй — процессы со значениями C = 1 в том же порядке, а третий — процессы со значениями C = 2 в том же порядке. Вывести ранги процессов R в созданных коммуникаторах (при этом значение R = 0 получат первые три процесса исходного коммуникатора MPI_COMM_WORLD). Затем, используя по два вызова функции MPI_Intercomm_create в каждом процессе, объединить созданные коммуникаторы в три интеркоммуникатора: первый должен содержать группы процессов со значениями C, равными 0 и 1, второй — группы со значениями 1 и 2, третий — группы со значениями 0 и 2 (таким образом, созданные интеркоммуникаторы будут образовывать кольцо, связывающее все три ранее созданные группы). Считая, что в первой группе процессов два следующих исходных числа обозначаются буквами X и Y, во второй группе — Y и Z, а в третьей — Z и X (в указанном порядке) и используя в каждом процессе по два вызова функций MPI_Send и MPI_Recv для созданных интеркоммуникаторов, поменять числа X для процессов одинакового ранга, входящих в первую и вторую группу, числа Y — для процессов одинакового ранга, входящих во вторую и третью группу, и числа Z — для процессов одинакового ранга, входящих в первую и третью группу. Вывести в каждом процессе полученные числа.

MPI8Inter5°. Количество процессов K кратно 4. В каждом процессе дано целое число X. Используя функции MPI_Comm_group, MPI_Group_range_incl и MPI_Comm_create, создать коммуникаторы, первый из которых содержит первую половину процессов (с рангами 0, 1, …, K/2 − 1 в указанном порядке), а второй — вторую половину (с рангами K/2, K/2 + 1, …, K − 1 в указанном порядке). Вывести ранги процессов R1 в созданных коммуникаторах. Затем объединить созданные коммуникаторы в интеркоммуникатор с помощью функции MPI_Intercomm_create. После этого, используя функцию MPI_Comm_create для созданного интеркоммуникатора, получить новый интеркоммуникатор, первая группа которого содержит процессы из первой группы исходного интеркоммуникатора с четными рангами (в том же порядке), а вторая группа — процессы из второй группы исходного интеркоммуникатора с нечетными рангами в обратном порядке (таким образом, в первую группу нового интеркоммуникатора будут входить процессы исходного коммуникатора MPI_COMM_WORLD с рангами 0, 2, …, K/2 − 2, а во вторую — с рангами K − 1, K − 3, …, K/2 + 1). Вывести ранги процессов R2, входящих в новый интеркоммуникатор. Используя функции MPI_Send и MPI_Recv для нового интеркоммуникатора, получить для каждого процесса число X из процесса того же ранга, входящего в другую группу этого интеркоммуникатора, и вывести полученные числа.

MPI8Inter6°. Количество процессов K кратно 4. В каждом процессе дано вещественное число X. Используя функции MPI_Comm_group, MPI_Group_range_incl и MPI_Comm_create, создать коммуникаторы, первый из которых содержит первую половину процессов (с рангами 0, 1, …, K/2 − 1 в указанном порядке), а второй — вторую половину (с рангами K/2, K/2 + 1, …, K − 1 в указанном порядке). Вывести ранги процессов R1 в созданных коммуникаторах. Затем объединить созданные коммуникаторы в интеркоммуникатор с помощью функции MPI_Intercomm_create. После этого, используя один вызов функции MPI_Comm_split для созданного интеркоммуникатора, получить два новых интеркоммуникатора. Первый из новых интеркоммуникаторов содержит процессы исходного интеркоммуникатора с четными рангами, а второй — с нечетными, причем процессы во второй группе каждого из новых интеркоммуникаторов должны располагаться в обратном порядке (таким образом, если использовать ранги процессов для исходного коммуникатора MPI_COMM_WORLD, то первый интеркоммуникатор содержит группы процессов ранга 0, 2, …, K/2 − 2 и K − 2, K − 4, …, K/2, а второй — группы процессов ранга 1, 3, …, K/2 − 1 и K − 1, K − 3, …, K/2 + 1). Вывести ранги процессов R2, входящих в новые интеркоммуникаторы. Используя функции MPI_Send и MPI_Recv для новых интеркоммуникаторов, получить для каждого процесса число X из процесса того же ранга, входящего в другую группу этого интеркоммуникатора, и вывести полученные числа.

MPI8Inter7°. Количество процессов K — четное число. В каждом процессе дано целое число C, равное либо 0, либо 1, причем известно, что в первой половине процессов дано единственное значение C = 1, а во второй половине количество значений C = 1 больше одного и, кроме того, имеется хотя бы одно значение C = 0. Используя функцию MPI_Comm_split, создать коммуникаторы, первый из которых содержит первую половину процессов (с рангами 0, 1, …, K/2 − 1 в указанном порядке), а второй — вторую половину (с рангами K/2, K/2 + 1, …, K − 1 в указанном порядке). Вывести ранги процессов R1 в созданных коммуникаторах. Затем объединить созданные коммуникаторы в интеркоммуникатор с помощью функции MPI_Intercomm_create. После этого, используя функцию MPI_Comm_split для созданного интеркоммуникатора, получить новый интеркоммуникатор, группы которого содержат процессы из соответствующих групп исходного интеркоммуникатора со значениями C = 1, взятые в обратном порядке (таким образом, в первую группу нового интеркоммуникатора будет входить единственный процесс, а количество процессов во второй группе будет лежать в диапазоне от 2 до K/2 − 1). Вывести ранги процессов R2, входящих в ту группу нового интеркоммуникатора, которая содержит более одного процесса. В единственном процессе первой группы нового интеркоммуникатора ввести массив Y из K2 целых чисел, где K2 — количество процессов во второй группе; в каждом процессе второй группы этого же интеркоммуникатора ввести по одному целому числу X. Используя требуемое количество вызовов функций MPI_Send и MPI_Recv для всех процессов нового интеркоммуникатора, получить в процессе первой группы все числа X из процессов второй группы (в порядке возрастания рангов этих процессов), а в каждом процессе второй группы ранга R2 (0, 1, …, K2 − 1) — элемент с индексом R2 из массива Y, данного в процессе первой группы. Вывести полученные числа.

Примечание. В реализации MPIСH 2 версии 1.3, используемой в задачнике, функция MPI_Comm_split приводит к ошибочной программе, если она применяется к интеркоммуникатору и при этом какие-либо из значений ее параметра color равны MPI_UNDEFINED. Таким образом, для корректной работы программ необходимо использовать только неотрицательные значения color. Кроме того, программа в дальнейшем может вести себя некорректно, если в результате применения функции MPI_Comm_split к интеркоммуникатору создаются пустые группы (это возможно, если для всех процессов одной из групп исходного интеркоммуникатора указываются одинаковые значения color, отличные от некоторых значений color для процессов другой группы).

MPI8Inter8°. В каждом процессе дано целое число C, лежащее в диапазоне от 0 до 2, причем известно, что и у процессов четного ранга, и у процессов нечетного ранга имеется хотя бы по одному из значений 0, 1, 2. Используя один вызов функции MPI_Comm_split, создать коммуникаторы, первый из которых содержит процессы с четными рангами (в порядке возрастания рангов), а второй — процессы с нечетными рангами (также в порядке возрастания рангов). Вывести ранги процессов R1 в созданных коммуникаторах. Затем объединить созданные коммуникаторы в интеркоммуникатор с помощью функции MPI_Intercomm_create. После этого, используя один вызов функции MPI_Comm_split для созданного интеркоммуникатора, получить три новых интеркоммуникатора, группы которых содержат процессы из соответствующих групп исходного интеркоммуникатора с одинаковыми значениями C, взятые в том же порядке (таким образом, в первую группу первого интеркоммуникатора будут входить процессы четного ранга со значениями C = 0, а, например, во вторую группу третьего интеркоммуникатора будут входить процессы нечетного ранга со значениями C = 2). Вывести ранги процессов R2 в новых интеркоммуникаторах. В процессах из первых групп созданных интеркоммуникаторов ввести по одному целому числу X, а в процессах из вторых групп — по одному целому числу Y. Используя требуемое количество вызовов функций MPI_Send и MPI_Recv для всех процессов новых интеркоммуникаторов, переслать все числа X каждому из процессов второй группы этого же коммуникатора, а все числа Y — каждому из процессов первой группы и вывести полученные числа в порядке возрастания рангов переславших их процессов.

MPI8Inter9°. Количество процессов K — четное число. В каждом процессе дано целое число C, лежащее в диапазоне от 0 до 2, причем известно, что в процессе ранга 0 дано число C = 1, а первое из значений C = 2 имеется у процесса ранга K/2. Используя функцию MPI_Comm_split, создать коммуникаторы, первый из которых содержит процессы со значениями C = 1 в том же порядке, а второй — процессы со значениями C = 2 в том же порядке. Вывести ранги процессов R в созданных коммуникаторах (если процесс не входит ни в один из созданных коммуникаторов, то вывести для него число −1). Затем объединить созданные коммуникаторы в интеркоммуникатор с помощью функции MPI_Intercomm_create. После этого ввести в процессах первой группы созданного интеркоммуникатора (соответствующей значениям C = 1) по одному целому числу X, а в процессах второй группы — по одному целому числу Y. Используя требуемое количество вызовов функций MPI_Send и MPI_Recv для всех процессов созданного интеркоммуникатора, переслать все числа X каждому из процессов второй группы этого коммуникатора, а все числа Y — каждому из процессов первой группы и вывести полученные числа в порядке возрастания рангов переславших их процессов.

Коллективные операции для интеркоммуникаторов

MPI8Inter10°. Количество процессов K — четное число. В каждом процессе дано целое число C, лежащее в диапазоне от 0 до 2, причем известно, что в процессе ранга 0 дано число C = 1, а первое из значений C = 2 имеется у процесса ранга K/2. Используя функцию MPI_Comm_split, создать коммуникаторы, первый из которых содержит процессы со значениями C = 1 в том же порядке, а второй — процессы со значениями C = 2 в том же порядке. Вывести ранги процессов R в созданных коммуникаторах (если процесс не входит ни в один из созданных коммуникаторов, то вывести для него число −1). Затем объединить созданные коммуникаторы в интеркоммуникатор с помощью функции MPI_Intercomm_create (группа, содержащая процессы со значениями C = 1, считается первой группой созданного интеркоммуникатора, а группа процессов со значениями C = 2 — второй). После этого ввести в процессах обеих групп созданного интеркоммуникатора целые числа R1 и R2. Значения чисел R1 во всех процессах совпадают и указывают ранг выделенного процесса первой группы; значения чисел R2 во всех процессах также совпадают и указывают ранг выделенного процесса второй группы. В выделенном процессе первой группы дан набор из трех целых чисел X, в выделенном процессе второй группы — набор из трех целых чисел Y. Используя по два вызова коллективной функции MPI_Bcast в каждом процессе созданного интеркоммуникатора, переслать набор чисел X во все процессы второй группы, а набор чисел Y во все процессы первой группы, после чего вывести полученные числа.

MPI8Inter11°. Количество процессов K — четное число. В каждом процессе дано целое число C, лежащее в диапазоне от 0 до 2, причем известно, что в процессе ранга 0 дано число C = 1, а первое из значений C = 2 имеется у процесса ранга K/2. Используя функцию MPI_Comm_split, создать коммуникаторы, первый из которых содержит процессы со значениями C = 1 в том же порядке, а второй — процессы со значениями C = 2 в том же порядке. Вывести ранги процессов R в созданных коммуникаторах (если процесс не входит ни в один из созданных коммуникаторов, то вывести для него число −1). Затем объединить созданные коммуникаторы в интеркоммуникатор с помощью функции MPI_Intercomm_create (группа, содержащая процессы со значениями C = 1, считается первой группой созданного интеркоммуникатора, а группа процессов со значениями C = 2 — второй). После этого ввести в процессах обеих групп созданного интеркоммуникатора целое число R1, которое совпадает во всех процессах и указывает ранг выделенного процесса первой группы. В выделенном процессе первой группы дан набор из K2 целых чисел X, где K2 — количество процессов во второй группе. Используя один вызов коллективной функции MPI_Scatter в каждом процессе созданного интеркоммуникатора, переслать по одному числу из набора X во все процессы второй группы (в порядке возрастания рангов процессов), после чего вывести полученные числа.

MPI8Inter12°. Количество процессов K — четное число. В каждом процессе дано целое число C, лежащее в диапазоне от 0 до 2, причем известно, что в процессе ранга 0 дано число C = 1, а первое из значений C = 2 имеется у процесса ранга K/2. Используя функцию MPI_Comm_split, создать коммуникаторы, первый из которых содержит процессы со значениями C = 1 в том же порядке, а второй — процессы со значениями C = 2 в том же порядке. Вывести ранги процессов R в созданных коммуникаторах (если процесс не входит ни в один из созданных коммуникаторов, то вывести для него число −1). Затем объединить созданные коммуникаторы в интеркоммуникатор с помощью функции MPI_Intercomm_create (группа, содержащая процессы со значениями C = 1, считается первой группой созданного интеркоммуникатора, а группа процессов со значениями C = 2 — второй). После этого ввести в процессах обеих групп созданного интеркоммуникатора целое число R2, которое совпадает во всех процессах и указывает ранг выделенного процесса второй группы. В каждом процессе первой группы дано по одному целому числу X. Используя один вызов коллективной функции MPI_Gather в каждом процессе созданного интеркоммуникатора, переслать исходные числа X (в порядке возрастания рангов содержащих их процессов) в выделенный процесс второй группы, после чего вывести в этом процессе полученные числа.

MPI8Inter13°. Количество процессов K — четное число. В каждом процессе дано целое число C, лежащее в диапазоне от 0 до 2, причем известно, что в процессе ранга 0 дано число C = 1, а первое из значений C = 2 имеется у процесса ранга K/2. Используя функцию MPI_Comm_split, создать коммуникаторы, первый из которых содержит процессы со значениями C = 1 в том же порядке, а второй — процессы со значениями C = 2 в том же порядке. Вывести ранги процессов R в созданных коммуникаторах (если процесс не входит ни в один из созданных коммуникаторов, то вывести для него число −1). Затем объединить созданные коммуникаторы в интеркоммуникатор с помощью функции MPI_Intercomm_create (группа, содержащая процессы со значениями C = 1, считается первой группой созданного интеркоммуникатора, а группа процессов со значениями C = 2 — второй). В каждом процессе первой группы дано по одному целому числу X, в каждом процессе второй группы дано по одному целому числу Y. Используя один вызов коллективной функции MPI_Allreduce в каждом процессе созданного интеркоммуникатора, получить в каждом процессе первой группы число Ymin — минимальное из исходных чисел Y, а в каждом процессе второй группы число Xmax — максимальное из исходных чисел X, после чего вывести полученные числа.

MPI8Inter14°. Количество процессов K — четное число. В каждом процессе дано целое число C, лежащее в диапазоне от 0 до 2, причем известно, что в процессе ранга 0 дано число C = 1, а первое из значений C = 2 имеется у процесса ранга K − 1. Используя функцию MPI_Comm_split, создать коммуникаторы, первый из которых содержит процессы со значениями C = 1 в том же порядке, а второй — процессы со значениями C = 2 в обратном порядке. Вывести ранги процессов R в созданных коммуникаторах (если процесс не входит ни в один из созданных коммуникаторов, то вывести для него число −1). Затем объединить созданные коммуникаторы в интеркоммуникатор с помощью функции MPI_Intercomm_create (группа, содержащая процессы со значениями C = 1, считается первой группой созданного интеркоммуникатора, а группа процессов со значениями C = 2 — второй). В каждом процессе первой группы дан массив целых чисел X размера K2, где K2 — количество процессов во второй группе, в каждом процессе второй группы дан массив целых чисел Y размера K1, где K1 — количество процессов в первой группе. Используя один вызов коллективной функции MPI_Alltoall в каждом процессе созданного интеркоммуникатора, переслать в процесс ранга R1 первой группы (R1 = 0, …, K1 − 1) элементы с индексом R1 из всех массивов Y, а в процесс ранга R2 второй группы (R2 = 0, …, K2 − 1) элементы с индексом R2 из всех массивов X. Вывести полученные числа в порядке возрастания рангов переславших их процессов.

Динамическое создание процессов

MPI8Inter15°. В каждом процессе дано вещественное число. Используя функцию MPI_Comm_spawn с первым параметром «ptprj.exe», создать один новый процесс. С помощью коллективной функции MPI_Reduce переслать в созданный процесс сумму исходных чисел и отобразить ее в разделе отладки, используя в этом процессе функцию Show. Затем с помощью коллективной функции MPI_Bcast переслать найденную сумму в исходные процессы и вывести эту сумму в каждом процессе.

MPI8Inter16°. В каждом процессе дан массив из K вещественных чисел, где K — количество процессов. Используя один вызов функции MPI_Comm_spawn с первым параметром «ptprj.exe», создать K новых процессов. С помощью коллективной функции MPI_Reduce_scatter_block переслать в созданный процесс ранга R (R = 0, …, K − 1) максимальный из элементов исходных массивов с индексом R и отобразить полученные максимальные элементы в разделе отладки, используя в каждом новом процессе функцию Show. Затем с помощью функций MPI_Send и MPI_Recv переслать найденный максимальный элемент из нового процесса ранга R (R = 0, …, K − 1) в исходный процесс того же ранга и вывести полученные элементы в исходных процессах.

MPI8Inter17°. Количество процессов K — четное число. В процессах ранга 0 и 1 даны массивы вещественных чисел размера K/2. Используя один вызов функции MPI_Comm_spawn с первым параметром «ptprj.exe», создать два новых процесса. Используя один вызов функции MPI_Comm_split для интеркоммуникатора, связанного с созданными процессами, создать два новых интеркоммуникатора: первый содержит группу исходных процессов четного ранга (0, …, K − 2), а также, в качестве второй группы, первый из новых процессов (ранга 0), второй содержит группу исходных процессов нечетного ранга (1, …, K − 1), а также, в качестве второй группы, второй из новых процессов (ранга 1). Используя функции MPI_Send в исходных процессах и функции MPI_Recv в новых процессах, переслать все исходные числа из первого процесса первой группы каждого интеркоммуникатора в единственный процесс, входящий в его вторую группу. Отобразить полученные числа в разделе отладки, используя в новых процессах функцию Show. Затем с помощью коллективной функции MPI_Scatter для интеркоммуникаторов переслать по одному числу из новых процессов во все процессы первой группы соответствующего интеркоммуникатора (в порядке возрастания рангов процессов) и вывести полученные числа.

MPI8Inter18°. Количество процессов K — четное число. В каждом процессе дан массив вещественных чисел размера K/2. Используя один вызов функции MPI_Comm_spawn с первым параметром «ptprj.exe», создать K новых процессов. Используя один вызов функции MPI_Comm_split для интеркоммуникатора, связанного с созданными процессами, создать два новых интеркоммуникатора: первый содержит группу исходных процессов четного ранга (0, …, K − 2), а также, в качестве второй группы, созданные процессы четного ранга, второй содержит группу исходных процессов нечетного ранга (1, …, K − 1), а также, в качестве второй группы, созданные процессы нечетного ранга. Для каждого из созданных интеркоммуникаторов выполнить следующие действия: среди элементов исходных массивов с индексом R (R = 0, …, K/2 − 1), входящих в первую группу каждого интеркоммуникатора, найти минимальный (для первого интеркоммуникатора) или максимальный (для второго) и переслать этот экстремальный элемент в тот из новых процессов, который имеет ранг R во второй группе соответствующего интеркоммуникатора (например, минимальный из первых элементов массивов, которые даны в исходных процессах четного ранга, следует переслать в первый из созданных процессов, а максимальный из первых элементов массивов, которые даны в исходных процессах нечетного ранга, следует переслать во второй из созданных процессов, поскольку этот процесс имеет ранг 0 в соответствующем интеркоммуникаторе). Для выполнения этих действий использовать коллективную функцию MPI_Reduce_scatter_block. Полученные экстремальные элементы отобразить в разделе отладки, используя в каждом новом процессе функцию Show. Затем с помощью коллективной функции MPI_Reduce найти минимальный элемент из тех минимумов, которые были получены во второй группе первого интеркоммуникатора, переслать и вывести его в первом процессе первой группы этого интеркоммуникатора (т. е. в процессе ранга 0 в исходном коммуникаторе MPI_COMM_WORLD), а также найти максимальный элемент из тех максимумов, которые были получены во второй группе второго интеркоммуникатора, переслать и вывести его в первом процессе первой группы этого интеркоммуникатора (т. е. в процессе ранга 1 в исходном коммуникаторе MPI_COMM_WORLD).

MPI8Inter19°. В главном процессе дан массив A из 2K целых чисел, где K — количество процессов. Используя один вызов функции MPI_Comm_spawn с первым параметром «ptprj.exe», создать K новых процессов. Используя функцию MPI_Intercomm_merge для интеркоммуникатора, связанного с созданными процессами, создать новый интракоммуникатор, содержащий как исходные, так и новые процессы (параметр high функции MPI_Intercomm_merge необходимо задать таким образом, чтобы в созданном интракоммуникаторе вначале располагались исходные, а затем созданные процессы). Используя коллективную функцию MPI_Scatter для нового интракоммуникатора, переслать по одному элементу массива A из главного процесса во все процессы приложения (как исходные, так и созданные) в порядке возрастания их рангов в новом интракоммуникаторе. В исходных процессах вывести полученные числа, в новых процессах отобразить полученные числа в разделе отладки, используя в этих процессах функцию Show. Затем, используя коллективную функцию MPI_Reduce в этом же интракоммуникаторе, переслать в исходный процесс ранга 1 сумму всех чисел и вывести ее в этом процессе.

MPI8Inter20°. Количество процессов K не делится на 4. В каждом процессе дано целое число A. Используя один вызов функции MPI_Comm_spawn с первым параметром «ptprj.exe», создать такое количество новых процессов (1, 2 или 3), чтобы общее число процессов K0 в приложении стало кратным 4. В каждом из созданных процессов задать значение числа A, равное −R − 1, где R — ранг созданного процесса. Используя функцию MPI_Intercomm_merge для интеркоммуникатора, связанного с созданными процессами, создать новый интракоммуникатор, содержащий как исходные, так и новые процессы (параметр high функции MPI_Intercomm_merge необходимо задать таким образом, чтобы в созданном интракоммуникаторе вначале располагались исходные, а затем новые процессы). Используя функцию MPI_Cart_create для созданного интракоммуникатора, определить для всех процессов декартову топологию в виде двумерной решетки размера (K0/4) × 4, являющейся периодической по второму измерению (порядок нумерации процессов оставить прежним). Используя функцию MPI_Cart_coords, определить координаты X, Y каждого процесса в данной решетке; в исходных процессах вывести эти координаты, в новых процессах отобразить координаты в разделе отладки с помощью функций Show, снабдив их комментариями «X = » и «Y = ». Выполнить циклический сдвиг значений A в каждом столбце созданной решетки с шагом −1 (т. е. в направлении убывания рангов процессов), используя для этого функции MPI_Cart_shift и MPI_Sendrecv_replace. В исходных процессах вывести полученные значения A, в новых процессах отобразить их в разделе отладки с помощью функции Show, снабдив комментарием «A = ».

MPI8Inter21°. В каждом процессе дано вещественное число: в главном процессе это число обозначается буквой A, в подчиненных процессах — буквой B. Используя два вызова функции MPI_Comm_spawn с первым параметром «ptprj.exe», создать две группы новых процессов: первая группа (группа-сервер) должна содержать один процесс, вторая группа (группа-клиент) должна содержать K − 1 процесс, где K — количество исходных процессов. Переслать в процесс группы-сервера число A из главного процесса, а в процессы группы-клиента — числа B из подчиненных процессов (в порядке возрастания рангов процессов) и отобразить полученные числа в разделе отладки, используя в каждом новом процессе функцию Show. С помощью функций MPI_Open_port, MPI_Publish_name и MPI_Comm_accept на стороне сервера и функций MPI_Lookup_name и MPI_Comm_connect на стороне клиента установить связь между двумя новыми группами процессов, создав для них новый интеркоммуникатор. Используя функции MPI_Send и MPI_Recv для этого интеркоммуникатора, получить в каждом процессе группы-клиента число A из процесса группы-сервера и найти сумму этого числа и числа B, полученного ранее из исходных подчиненных процессов. Отобразить найденную сумму A + B в разделе отладки, используя в каждом процессе группы-клиента функцию Show, а также переслать эту сумму в соответствующий исходный подчиненный процесс и вывести полученную сумму в этом процессе (сумма, найденная в процессе ранга R группы-клиента, должна быть переслана в исходный процесс ранга R + 1).

Примечание. В программе необходимо обеспечить такую последовательность действий, чтобы вызов функции MPI_Lookup_name в процессах клиента гарантированно выполнялся после вызова функции MPI_Publish_name в процессе сервера. Можно, например, использовать функцию MPI_Barrier для исходных процессов и процесса сервера, вызвав ее в процессе сервера только после завершения вызова функции MPI_Publish_name, и вызвать функцию MPI_Comm_spawn для создания группы-клиента уже после выхода из функции MPI_Barrier в исходных процессах.

MPI8Inter22°. В каждом процессе дано целое число N, которое может принимать три значения: 0, 1 и K (K > 1). Известно, что имеется ровно один процесс со значением N = 1 и ровно K процессов со значением N = K. В тех процессах, в которых число N не равно 0, также дано целое число A. Используя функцию MPI_Comm_split, разбить исходный коммуникатор MPI_COMM_WORLD на два, в каждый из которых входят процессы с одинаковым ненулевым значением N. Используя один вызов функции MPI_Comm_spawn для каждого из созданных коммуникаторов, создать два набора новых процессов; число новых процессов должно совпадать с количеством процессов в соответствующем коммуникаторе (таким образом, в одной новой группе будет содержаться 1 процесс, в другой — K процессов). Переслать в каждый из новых процессов число A из того исходного процесса, ранг которого в созданном коммуникаторе совпадает с рангом нового процесса. Отобразить полученные числа в разделе отладки, используя в каждом новом процессе функцию Show. Считая новую группу, состоящую из одного процесса, группой-сервером, а новую группу из K процессов — группой-клиентом, установить между ними связь с помощью функций MPI_Open_port, MPI_Publish_name и MPI_Comm_accept на стороне сервера и MPI_Lookup_name и MPI_Comm_connect на стороне клиента. Используя коллективную функцию MPI_Gather для интеркоммуникатора, связывающего группу-клиент и группу-сервер, переслать все числа A из процессов группы-клиента в процесс группы-сервера и отобразить полученные числа в разделе отладки, используя несколько вызовов функции Show в процессе группы-сервера. Кроме того, переслать эти числа с помощью функций MPI_Send и MPI_Recv из процесса группы-сервера в тот исходный процесс, который создал группу-сервер, и вывести полученные числа в этом исходном процессе.

Примечание. В программе необходимо обеспечить такую последовательность действий, чтобы вызов функции MPI_Lookup_name в процессах клиента гарантированно выполнялся после вызова функции MPI_Publish_name в процессе сервера. Можно, например, поступить следующим образом. Для пересылки числа A в процесс группы-сервера применить функцию MPI_Ssend, вызвав после нее функцию MPI_Barrier для исходного коммуникатора MPI_COMM_WORLD и организовав прием этого числа в процессе группы-сервера только после выполнения функции MPI_Publish_name. В остальных процессах исходного коммуникатора MPI_COMM_WORLD следует вначале вызвать функцию MPI_Barrier, а затем организовать пересылку чисел A в созданные процессы группы-клиента. Таким образом, любой из процессов группы-клиента получит число A только тогда, когда процесс группы-сервера уже выполнит вызов функции MPI_Publish_name.


PrevNext

 

Рейтинг@Mail.ru

Разработка сайта:
М. Э. Абрамян, В. Н. Брагилевский

Последнее обновление:
01.01.2024