Скачиваний:
0
Добавлен:
27.12.2025
Размер:
650.98 Кб
Скачать

МИНОБРНАУКИ РОССИИ САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ «ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА) Кафедра САПР

ОТЧЕТ по лабораторной работе №4

по дисциплине «Архитектура параллельных вычислительных систем» ТЕМА: «Решение систем линейных алгебраических уравнений прямыми методами на системах с общей памятью»

Вариант 3

Студенты гр. 1302

Харитонов А.А.

Наволоцкий И.Р.

Солончак И.П.

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

Костичев С.В.

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

2025

Цель работы

Практическое освоение методов решения систем линейных алгебраических уравнений прямыми методами на вычислительных системах с общей памятью.

1.Задание на лабораторную работу

1.1.Разработать алгоритмы решения СЛАУ вида = методом Гаусса-Жордана для последовательных и параллельных вычислений.

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

1.3.Запустить программы для следующих значений размерности СЛАУ: 5, 10, 100, 500, 1000, 5000, 10000.

1.4.Оценить размерность СЛАУ, при которой эффективнее использовать алгоритмы последовательного и параллельного вычислений для разного числа потоков (по крайней мере для меньшего, равного и большего, чем число процессоров).

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

2. Программное и аппаратное окружение при выполнении работы

При выполнении лабораторной работы использовался ноутбук Apple MacBook Air с чипом M1, содержащим 8-ядерный CPU и 7-ядерный GPU, а также 8 Гб оперативной памяти. Работа выполнялась под управлением macOS Sequoia 15.7.1.

Среда разработки: Visual Studio Code 1.105.1, система сборки: CMake, управляемый через расширение CMake Tools в VS Code.

2

3. Формализация задачи Справка:

Метод Гаусса-Жордана – это прямой метод решения систем линейных алгебраических уравнений (СЛАУ). Он является модификацией метода Гаусса. Суть метода заключается в приведении расширенной матрицы системы к диагональному (или единичному) виду путем элементарных преобразований строк. В отличие от метода Гаусса, здесь исключение неизвестных проводится не только ниже, но и выше главной диагонали, что позволяет получить значение неизвестных ! сразу после завершения алгоритма без обратного хода.

Алгоритм работы программы:

1.Инициализация MPI: инициализируется среда MPI, определяется общее число потоков (threads) и ранг текущего потока.

2.Компиляция и запуск: Исходный код 1302_3_4.cpp компилируется компилятором mpic++ с флагами оптимизации (-O3, -march=native, -ffast-math).

3.Проверка корректности (Example Test):

Запускается функция runExample.

Решается заранее заданная СЛАУ размерности 2 × 2

( " + 2 # = 3, 2 " # = 1).

Производится сравнение полученного результата с

ожидаемым

( " = 1, # = 1)

для

подтверждения

работоспособности алгоритма распределения строк.

4.Основной цикл тестов:

Скрипт-обертка (.sh) запускает программу для разного количества потоков: {2, 4, 6, 8, 10, 12, 14, 16}.

Для первого запуска выполняется измерение времени как последовательного, так и параллельного алгоритма для всех размерностей из набора TEST_SIZES.

3

Для остальных запусков последовательная часть пропускается (флаг --skip-serial) для экономии времени.

5.Для каждой размерности выполняются шаги:

a.Генерация данных:

На главном потоке (rank 0) генерируется СЛАУ с использованием std::mt19937 и std::random_device для обеспечения случайности значений при каждом запуске.

b.Распределение данных (Data Decomposition):

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

c.Параллельное решение (метод Гаусса-Жордана):

Цикл проходит по всем строкам от 0 до − 1 (выбор ведущего элемента).

Определяется поток-владелец текущей ведущей

строки .

Владелец нормализует строку (делит на диагональный элемент) и рассылает её всем остальным потокам с помощью MPI_Bcast.

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

d.Измерение времени:

Время выполнения замеряется с помощью MPI_Wtime().

6.Сбор и вывод результатов:

Результаты работы скрипта (время выполнения для

различных конфигураций) собираются, сортируются и

4

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

4.Примеры работы программы

Вычисления производились на матрицах размерностью от 5 до 10000 элементов с элементами типа данных double.

Исходный код программы приведён в приложении А. Блок-схемы алгоритмов приведены в приложении Б.

4.1.Демонстрация работы программы

При запуске программа сначала выполняет вычисления в демонстрационном режиме для решения системы уравнений малой размерности (2x2), точное решение которой известно заранее ( " = 1, # = 1). Как видно на рисунке 1, программа выводит на экран результат работы метода Гаусса-Жордана, подтверждая, что вычисленные корни совпадают с ожидаемыми.

Рисунок 1 – Пример работы программы при решении СЛАУ 2x2

Этот шаг служит для визуального подтверждения математической корректности реализации метода Гаусса-Жордана и логики распределения данных (MPI Scatter/Gather) перед переходом к масштабным замерам производительности.

5

На рисунке 2 представлен фрагмент лога работы программы в режиме бенчмарка. Видно, что скрипт автоматизации циклически запускает MPIпрограмму для различного числа потоков (threads) для того, чтобы визуально отслеживать прогресс работы программы.

Рисунок 2 – Лог работы скрипта автоматизации запуска тестов для разного числа потоков

4.2.Анализ результатов производительности

После верификации программа выполняет серию автоматизированных тестов для измерения времени решения СЛАУ разных размерностей (от 5 до 10000 неизвестных) с использованием последовательного и параллельного (MPI) алгоритмов. Результаты замеров для разного числа потоков сведены в общую таблицу, представленную на рисунке 3.

Рисунок 3 – Итоговая сводная таблица производительности для последовательного и параллельного метода Гаусса-Жордана

6

4.2.1. Влияние размера массива на время выполнения

Метод Гаусса-Жордана имеет кубическую временную сложность( $). Полученные экспериментальные данные для последовательной версии наглядно подтверждают эту зависимость:

При увеличении размера в 5 раз (от 1000 до 5000 элементов) время выполнения выросло примерно в 134 раза (с 302.79 мс до 40503.13 мс), что близко к теоретическому росту в 125 раз (5$). Небольшое отклонение объясняется накладными расходами на работу с памятью при выходе за пределы кэша.

При увеличении размера в 2 раза (от 5000 до 10000 элементов) время выполнения выросло примерно в 8.6 раза (с 40503.13 мс до 347620.54 мс), что практически совпадает с теоретическим ростом в 8 раз (2$).

Это подтверждает, что сложность алгоритма является доминирующим фактором, и с ростом размерности матрицы необходимость в параллельных вычислениях резко возрастает (последовательный расчет для = 10000 занял почти 6 минут).

4.2.2. Эффективность параллельных вычислений

Сравнение последовательного и параллельного (MPI) методов показывает наличие «порога вхождения», обусловленного накладными расходами на межпроцессное взаимодействие (Scatter, Broadcast).

На малых размерах (5, 10, 100): параллельный алгоритм работает значительно медленнее последовательного. Например, для = 100 последовательная версия занимает 0.207 мс, а версия на 2 потоках – 0.339 мс. Это объясняется тем, что время на пересылку данных между процессами превышает полезную вычислительную нагрузку.

На больших размерах (5000 и 10000): начиная с = 500, параллельная версия становится эффективнее.

7

o Для = 10000 последовательная версия выполняется за 347620 мс.

o Лучший параллельный результат (16 потоков) составляет 153450 мс.

o Ускорение составляет 2.26 раза.

Это демонстрирует, что для MPI-реализации на общей памяти точка безубыточности находится на размерностях около = 500, после чего параллелизм дает выигрыш.

4.2.3. Влияние количества потоков и масштабируемость

Анализ времени выполнения MPI-алгоритма при разном количестве потоков выявляет ограничение аппаратной масштабируемости и специфику метода.

Скачок производительности (2-4 потока): на размере = 5000

при переходе от последовательного режима к 2 потокам время сокращается с 40503 мс до 25355 мс. При переходе к 4 потокам – до 20694 мс. Это демонстрирует работу параллелизма на производительных ядрах процессора.

Насыщение (после 4-6 потоков):

o На 4 потоках время для = 10000 составляет 156212 мс. o На 16 потоках время составляет 153450 мс.

o Прирост производительности при увеличении числа потоков

с4 до 16 составляет менее 2%. Это явление связано с двумя факторами:

1.Архитектура Apple M1: чип имеет 4 высокопроизводительных ядра. Использование числа потоков более 4 вынуждает задействовать энергоэффективные ядра, которые значительно медленнее в вычислениях с плавающей точкой, что нивелирует выигрыш от распараллеливания.

2.Ограничение пропускной способности памяти (Memory Wall): прямой метод Гаусса-Жордана требует прокачки

8

больших объемов данных через шину памяти. При использовании MPI на общей памяти накладные расходы на копирование данных (broadcast каждой строки всем процессам) создают «узкое место», не позволяя масштабироваться линейно.

Таким образом, для данной реализации оптимальным является использование числа потоков, равного количеству производительных ядер (4), так как дальнейшее увеличение не дает значительного экономического эффекта.

Вывод

В ходе лабораторной работы были реализованы и сравнены последовательный и параллельный методы решения СЛАУ при помощи метода Гаусса-Жордана с использованием библиотеки MPI.

Анализ показал, что параллельная версия демонстрирует эффективность на больших матрицах (от 500 элементов), достигая ускорения более чем в 2.2 раза на матрице размерностью 10000. На малых данных использование MPI нецелесообразно из-за накладных расходов на коммуникации.

Было установлено, что производительность масштабируема до достижения предела производительных ядер процессора (4 потока). Дальнейшее увеличение числа потоков выводит производительность на плато. Это свидетельствует о том, что ограничивающим фактором для данного класса задач на системах с общей памятью становится пропускная способность подсистемы памяти и смешанная архитектура ядер процессора.

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

9

ПРИЛОЖЕНИЕ А Листинги исходного кода программы

1302_3_4.cpp

#include <iostream> #include <vector> #include <cmath> #include <iomanip> #include <cstdlib> #include <ctime> #include <string> #include <random> #include <mpi.h>

using namespace std;

// Размерности СЛАУ для тестов

const vector<int> TEST_SIZES = {5, 10, 100, 500, 1000, 5000, 10000};

vector<double> generateSystem(int N) { // Плоский массив

vector<double> matrix(N * (size_t)(N + 1));

std::random_device rd; std::mt19937 gen(rd());

std::uniform_int_distribution<> distrib(1, 100);

for (size_t i = 0; i < matrix.size(); ++i) { matrix[i] = (double)distrib(gen);

}

// Диагональное преобладание

10