Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

па-пми / лр-1

.docx
Скачиваний:
0
Добавлен:
10.06.2026
Размер:
525.37 Кб
Скачать

МИНОБРНАУКИ РОССИИ

Санкт-Петербургский государственный

электротехнический университет

«ЛЭТИ» им. В.И. Ульянова (Ленина)

Кафедра МО ЭВМ

отчет

по лабораторной работе №1

по дисциплине «Параллельные алгоритмы»

Тема: Запуск параллельной программы на различном числе

одновременно работающих процессов, упорядочение вывода результатов.

Студентка гр. 3384

Преподаватель

Татаринов Ю.С.

Санкт-Петербург

2025

Цель работы.

На практике применить знания, касающиеся принципов работы и основных функций MPI. Написать параллельную программу, модифицировать ее и сравнить полученные результаты.

Задание.

Задание 1. Все процессы, кроме процесса с рангом 0, передают значение своего ранга нулевому процессу. Процесс с рангом 0 сначала печатает значение своего ранга, а далее принимает сообщения с рангами процессов и также печатает их значения. При этом важно отметить, что порядок приема сообщений заранее не определен и зависит от условий выполнения параллельной программы (более того, этот порядок может изменяться от запуска к запуску).

2. Проанализировать порядок вывода сообщений на экран. Для этого запустит программу несколько раз при фиксированном числе процессов, например -8ми. Вывести правило, определяющее порядок вывода сообщений.

3. Выполнить требования к содержанию отчета для задания 1.

Задание 2. Модифицировать программу таким образом, чтобы порядок вывода сообщений на экран соответствовал номеру соответствующего процесса.

1. Выполнить требования к содержанию отчета для задания 2.

2. Сравнить результаты работы двух программ.

Выполнение работы.

Задание 1. В реализованной программе сначала происходит синхронизация всех процессов, а затем начинается замер времени, в который включён только обмен сообщениями. Процессы с рангом не равным нулю отправляют свой ранг процессу с рангом ноль, а процесс ноль последовательно принимает эти ранги и сохраняет их в массив в порядке прихода. После завершения обмена вычисление времени прекращается и процесс ноль выводит сохранённые ранги и измеренное время работы программы. Результат работы программы на 8 процессорах представлен в таблице 1.

Таблица 1 – Результаты работы программы с 8 процессами

Номер теста

Результат вывода программы

Время выполнения, с

1

Hello from process 0

Hello from process 3

Hello from process 4

Hello from process 5

Hello from process 6

Hello from process 2

Hello from process 7

Hello from process 1

0.000098

2

Hello from process 0

Hello from process 2

Hello from process 4

Hello from process 7

Hello from process 5

Hello from process 1

Hello from process 3

Hello from process 6

0.000063

3

Hello from process 0

Hello from process 4

Hello from process 1

Hello from process 2

Hello from process 3

Hello from process 5

Hello from process 6

Hello from process 7

0.000056

После проведения тестов нетрудно заметить, что процесс с рангом 0 всегда выводится первым, а последующие строки печатаются в том порядке, в котором сообщения фактически приходят к процессу 0. Этот порядок недетерминирован и может меняться от запуска к запуску. Причины просты: все остальные процессы отправляют сообщения почти одновременно, но из-за работы планировщика операционной системы, небольших различий во времени выполнения, очередей в различных буферах и других причин сообщения разных процессов достигают корневой в разное время.

Более подробное тестирование программы на различных числах процессоров см. в приложении B таблицы 2 и 3.

Графики.

На рисунке 1 показана зависимость среднего времени выполнения программы от числа процессов. Среднее время работы вычислялось как среднее на основе работы теста десять раз. По рисунку видно, что с увеличение числа процессов возрастает и время работы программы.

Рисунок 1 – График зависимости времени выполнения программы от числа процессов

На рисунке 2 изображен график замедления функции.

Рисунок 2 – График замедления

Сеть Петри.

На рисунке 3 изображена Сеть Петри для трех процессов.

Рисунок 3 – Сеть Петри

Задание 2. Программа была модифицирована так, что изменилась логика приёма и хранения сообщений на корневом процессе. Теперь каждое входящее сообщение сохраняется в ячейку массива, индекс которой соответствует номеру отправителя. Массив выделяется размером, равным количеству процессов, где каждая ячейка инициализируется значением −1 для маркировки того, что сообщение от процесса еще не поступило. Перед записью выполняется проверка, что номер находится в допустимом диапазоне. После приёма всех сообщений выполняется синхронизация. Для синхронизации используется блокирующая коллективная операция MPI_Barrier на коммуникаторе MPI_COMM_WORLD. Первая синхронизация выполняется после начального вывода, чтобы исключить ввод/вывод из замера времени, вторая происходит после приёма всех сообщений, чтобы гарантировать, что все процессы завершили отправки/приёмы до остановки таймера и финального вывода. Вывод производится в порядке возрастания номеров процессов, при отсутствии сообщения для конкретного номера выводится пометка «сообщение не получено».

Тестирование модифицированной программы на различных числах процессоров см. в приложении B таблицу 4.

Графики.

На рисунке 4 показана зависимость среднего времени выполнения программы от числа процессов. Среднее время работы вычислялось как среднее на основе работы теста десять раз. По рисунку видно, что с увеличением числа задействованных процессов растет и время выполнения программы.

Рисунок 4 – График зависимости времени выполнения программы от числа процессов

На рисунке 5 изображен график замедления функции.

Рисунок 5 – График замедления

Сеть Петри.

На рисунке 6 изображена Сеть Петри для модифицированной программы.

Рисунок 6 – Сеть Петри для модифицированной программы

Разработанный программный код см. в приложении А.

Выводы.

Выполненная работа включала реализацию и тестирование двух версий параллельной MPI программы, первая из которых принимала сообщения в недетерминированном порядке, а вторая обеспечивала вывод сообщений в упорядоченном виде по возрастанию номеров процессов.

Основные причины недетерминированности связаны с одновременной отправкой сообщений разными процессами, воздействием планировщика операционной системы, очередями в буферах и малыми различиями во времени выполнения операций отправки. Для получения детерминированного вывода программа была модифицирована так, что корневой процесс выделял массив, инициализировал его значением −1 и сохранял каждый пришедший ранг в ячейку с индексом, равным номеру отправителя. Такая логика позволила в конце вывести сообщения по возрастанию номеров. Для корректного измерения времени были использованы две синхронизации MPI_Barrier, чтобы убедиться в завершении всех отправок и приёмов.

Полученные эксперименты показали, что среднее время выполнения растёт с увеличением числа процессов, что указывает на накладные расходы на синхронизацию и управление коммуникацией при масштабировании. Анализ графика замедления показал ограниченную масштабируемость подхода, так как при большом количестве процессов корневой узел становится узким местом.

Сравнение времени работы программ показало, что вторая программа работает немного медленнее. Это связано с дополнительными операциями в коде инициализацией массива, проверками условий и обработкой возможных ошибок. При небольшом числе процессов эти дополнительные операции влияют на время выполнения, однако, когда процессов становится больше 16, разница уменьшается, потому что основное время занимает взаимодействие между процессами.

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

Приложение А Исходный код программы

Main.c

#include "mpi.h"

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char** argv) {

MPI_Init(&argc, &argv);

int ProcRank, ProcCount;

MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);

MPI_Comm_size(MPI_COMM_WORLD, &ProcCount);

if (ProcRank == 0) {

printf("\n Hello from process %2d\n", ProcRank);

fflush(stdout);

}

MPI_Barrier(MPI_COMM_WORLD);

double t_start = MPI_Wtime();

if (ProcRank == 0) {

int *recv_ranks = NULL;

if (ProcCount > 1) {

recv_ranks = (int*)malloc((ProcCount-1) * sizeof(int));

if (recv_ranks == NULL) {

fprintf(stderr, "Memory allocation failed\n");

MPI_Abort(MPI_COMM_WORLD, 1);

}

}

for (int i = 0; i < ProcCount-1; ++i) {

int RecvRank;

MPI_Status status;

MPI_Recv(&RecvRank,1,MPI_INT,MPI_ANY_SOURCE,MPI_ANY_TAG, MPI_COMM_WORLD,&status);

recv_ranks[i] = RecvRank;

}

MPI_Barrier(MPI_COMM_WORLD);

double t_end = MPI_Wtime();

double elapsed = t_end - t_start;

for (int i = 0; i < ProcCount - 1; ++i) {

printf("Hello from process %2d\n", recv_ranks[i]);

}

printf("Elapsed_time_sec = %.6f\n", elapsed);

free(recv_ranks);

} else {

MPI_Send(&ProcRank, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);

MPI_Barrier(MPI_COMM_WORLD);

}

MPI_Finalize();

return 0;

}

Main_2.c

#include <mpi.h>

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char** argv) {

MPI_Init(&argc, &argv);

int ProcRank, ProcCount;

MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);

MPI_Comm_size(MPI_COMM_WORLD, &ProcCount);

if (ProcRank == 0) {

printf("Hello from process %2d\n", ProcRank);

fflush(stdout);

}

MPI_Barrier(MPI_COMM_WORLD);

double t_start = MPI_Wtime();

if (ProcRank == 0) {

int *recv_ranks = NULL;

if (ProcCount > 1) {

recv_ranks = (int*)malloc(ProcCount * sizeof(int));

if (recv_ranks == NULL) {

fprintf(stderr, "Memory allocation failed\n");

MPI_Abort(MPI_COMM_WORLD, 1);

}

for (int i = 0; i < ProcCount; ++i) recv_ranks[i] = -1;

}

for (int i = 0; i < ProcCount - 1; ++i) {

int RecvRank;

MPI_Status status;

MPI_Recv(&RecvRank,1,MPI_INT,MPI_ANY_SOURCE,MPI_ANY_TAG, MPI_COMM_WORLD, &status);

if (RecvRank >= 0 && RecvRank < ProcCount) {

recv_ranks[RecvRank] = RecvRank;

} else {

fprintf(stderr, "Received unexpected rank value %d\n", RecvRank);

}

}

MPI_Barrier(MPI_COMM_WORLD);

double t_end = MPI_Wtime();

double elapsed = t_end - t_start;

for (int r = 1; r < ProcCount; ++r) {

if (recv_ranks && recv_ranks[r] != -1) {

printf("Hello from process %2d\n", recv_ranks[r]);

} else {

printf("Hello from process %2d (no message received)\n", r);

}

}

printf("Elapsed_time_sec = %.6f\n", elapsed);

free(recv_ranks);

} else {

MPI_Send(&ProcRank, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);

MPI_Barrier(MPI_COMM_WORLD);

}

MPI_Finalize();

return 0;

}

Приложение B Тестирование

В таблицах 2 и 3 представлено тестирование задания 1.

Таблица 2 - Результаты тестирования на 1, 2 и 4 процессах

Число процессов

Вывод программы

Время выполнения

1

Hello from process 0

0.000000

Hello from process 0

0.000000

Hello from process 0

0.000000

2

Hello from process 0

Hello from process 1

0.000047

Hello from process 0

Hello from process 1

0.000005

Hello from process 0

Hello from process 1

0.000007

Hello from process 0

Hello from process 1

0.000037

Hello from process 0

Hello from process 1

0.000028

4

Hello from process 0

Hello from process 2

Hello from process 3

Hello from process 1

0.000015

Hello from process 0

Hello from process 2

Hello from process 1

Hello from process 3

0.000006

Hello from process 0

Hello from process 2

Hello from process 1

Hello from process 3

0.000068

Hello from process 0

Hello from process 1

Hello from process 2

Hello from process 3

0.000008

Hello from process 0

Hello from process 1

Hello from process 3

Hello from process 2

0.000006

В таблице 3 представлен сокращенный вывод программы, где через запятую перечислены в каком порядке были получены сообщения от процессов.

Таблица 3 - Результаты тестирования на 8, 16 и 32 процессах

Число процессов

Вывод программы

Время выполнения

8

Hello from process 0, 2, 1, 3, 5, 7, 4, 6

0.000083

Hello from process 0, 1, 2, 3, 4, 5, 6, 7

0.000031

Hello from process 0, 7, 3, 4, 6, 2, 1, 5

0.000088

Hello from process 0, 1, 5, 4, 6, 7, 2, 3

0.000035

Hello from process 0, 5, 1, 2, 3, 4, 6, 7

0.000181

16

Hello from process 0, 8, 1, 2, 3, 4, 5, 7, 9, 10, 11, 12, 13, 14, 15, 6

0.000106

Hello from process 0, 4, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

0.000077

Hello from process 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 8

0.000013

Hello from process 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

0.000006

Hello from process 0, 4, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

0.000125

32

Hello from process 0, 1, 2, 3, 11, 27, 16, 17, 18, 19, 23, 5, 7, 10, 21, 12, 13, 14, 15, 20, 22, 24, 25, 26, 28, 29, 30, 4, 6, 8, 9, 31

0.000367

Hello from process 0, 22, 16, 23, 24, 25, 27, 28, 29, 30, 31, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 20, 21, 26, 18, 2

0.000260

Hello from process 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31

0.000086

Hello from process 0, 2, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 26, 3

0.000198

В таблице 4 представлено тестирование задания 2. В качестве вывода программы представлена просто последовательность процессов.

Таблица 4 - Результаты тестирования на 1, 2, 4, 8, 16 и 32 процессах

Число процессов

Вывод программы

Время выполнения

1

Hello from process 0

0.000000

Hello from process 0

0.000000

2

Hello from process 0, 1

0.000005

Hello from process 0, 1

0.000039

Hello from process 0, 1

0.000004

4

Hello from process 0, 1, 2, 3

0.000020

Hello from process 0, 1, 2, 3

0.000083

Hello from process 0, 1, 2, 3

0.000047

Hello from process 0, 1, 2, 3

0.000036

8

Hello from process 0, 1, 2, 3, 4, 5, 6, 7

0.000016

Hello from process 0, 1, 2, 3, 4, 5, 6, 7

0.000075

Hello from process 0, 1, 2, 3, 4, 5, 6, 7

0.000005

Hello from process 0, 1, 2, 3, 4, 5, 6, 7

0.000046

16

Hello from process 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

0.000122

Hello from process 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

0.000080

Hello from process 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

0.000024

Hello from process 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

0.000070

32

Hello from process 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31

0.000165

Hello from process 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31

0.000328

Hello from process 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31

0.000181

Hello from process 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31

0.000171

Соседние файлы в папке па-пми