diff --git a/zhimolostnova_anna_lab_5/README.md b/zhimolostnova_anna_lab_5/README.md new file mode 100644 index 0000000..ed266a5 --- /dev/null +++ b/zhimolostnova_anna_lab_5/README.md @@ -0,0 +1,75 @@ +# Отчет по лабораторной работе №5 + +## Описание задачи + +В лабораторной работе необходимо реализовать два алгоритма для умножения квадратных матриц: +последовательный и параллельный. Параллельный алгоритм должен поддерживать настройку количества потоков, +что позволит гибко распределять нагрузку. Бенчмарки проводились на матрицах размером 100x100, 300x300 +и 500x500 для анализа производительности каждого алгоритма. + +## Структура проекта + +Проект состоит из двух файлов с реализацией алгоритмов: + +- regular.go — реализация последовательного умножения матриц. +- parallel.go — реализация параллельного умножения матриц с заданным количеством потоков. +- matrix.go (в папке util) — вспомогательные функции для создания матриц. + +## Результаты + +### Последовательное умножение + +![img_1.png](images%2Fimg_1.png) + +| Размер матрицы | Время выполнения | +|-----------------|------------------| +| 100x100 | 2.1442ms | +| 300x300 | 59.4206ms | +| 500x500 | 382.7277ms | + +### Параллельное умножение + +![img.png](images%2Fimg.png) + +| Размер матрицы | Количество потоков | Время выполнения | +|----------------|--------------------|------------------| +| 100x100 | 2 | 1.1137ms | +| 100x100 | 4 | 524.1µs | +| 100x100 | 6 | 546.2µs | +| 100x100 | 8 | 527.6µs | +| 300x300 | 2 | 41.6503ms | +| 300x300 | 4 | 25.7563ms | +| 300x300 | 6 | 19.4356ms | +| 300x300 | 8 | 15.0006ms | +| 500x500 | 2 | 216.1878ms | +| 500x500 | 4 | 119.4361ms | +| 500x500 | 6 | 98.5036ms | +| 500x500 | 8 | 76.9725ms | + +## Анализ полученных данных + +1. Последовательное умножение: + - Время выполнения линейно увеличивается с ростом размера матрицы. Это связано с тем, + что алгоритм работает с комплексностью O(n³), где n — размер матрицы. + - Для больших матриц (500x500) время выполнения становится заметно больше, что подчеркивает + ограниченность этого метода при работе с большими объемами данных. +2. Параллельное умножение: + - Параллельный алгоритм показал значительное улучшение времени выполнения по сравнению с + последовательным, особенно при увеличении количества потоков. + - Например, для матриц 100x100 время выполнения снизилось с 1.6ms до 524.1µs при использовании + 4 потоков. + - Для матриц большего размера (500x500) прирост производительности также существенный: + с 393.65ms (последовательное умножение) до 76.97ms при 8 потоках. + - Однако, начиная с 6 потоков, улучшения становятся менее значительными. Это связано с накладными + расходами на синхронизацию потоков и передачу данных между ними. При небольших размерах матриц такие накладные расходы могут нивелировать прирост производительности. +3. Заключение: + - Параллельный алгоритм значительно превосходит последовательный при увеличении размера + матриц и количества потоков. Однако для небольших матриц с увеличением количества потоков, прирост + производительности не всегда оправдан из-за накладных расходов на управление потоками. + - Оптимальное количество потоков зависит от размера матриц: для небольших матриц 4 потока дают + значительное улучшение, а для матриц большего размера (500x500) лучше использовать 8 потоков для + максимальной эффективности. + +## Демонстрационное видео + +Видеозапись доступна по адресу: [https://vk.com/video193898050_456240873](https://vk.com/video193898050_456240873) \ No newline at end of file diff --git a/zhimolostnova_anna_lab_5/images/img.png b/zhimolostnova_anna_lab_5/images/img.png new file mode 100644 index 0000000..96221f4 Binary files /dev/null and b/zhimolostnova_anna_lab_5/images/img.png differ diff --git a/zhimolostnova_anna_lab_5/images/img_1.png b/zhimolostnova_anna_lab_5/images/img_1.png new file mode 100644 index 0000000..b8a44e5 Binary files /dev/null and b/zhimolostnova_anna_lab_5/images/img_1.png differ diff --git a/zhimolostnova_anna_lab_5/parallel.go b/zhimolostnova_anna_lab_5/parallel.go new file mode 100644 index 0000000..715ccff --- /dev/null +++ b/zhimolostnova_anna_lab_5/parallel.go @@ -0,0 +1,72 @@ +package main + +import ( + "fmt" + "strconv" + "sync" + "time" + "zhimolostnova_anna_lab_5/util" +) + +// Параллельное умножение матриц +func multiplyMatricesParallel(a, b [][]int, threads int) [][]int { + size := len(a) + result := make([][]int, size) + for i := range result { + result[i] = make([]int, size) + } + + // Функция для обработки части работы потока + worker := func(startRow, endRow int, wg *sync.WaitGroup) { + defer wg.Done() + for i := startRow; i < endRow; i++ { + for j := 0; j < size; j++ { + for k := 0; k < size; k++ { + result[i][j] += a[i][k] * b[k][j] + } + } + } + } + + // Запуск потоков + var wg sync.WaitGroup + rowsPerThread := size / threads + for i := 0; i < threads; i++ { + startRow := i * rowsPerThread + endRow := startRow + rowsPerThread + if i == threads-1 { + endRow = size + } + wg.Add(1) + go worker(startRow, endRow, &wg) + } + + wg.Wait() + return result +} + +func benchmarkMatrixMultiplication(sizes []int, threadsList []int) { + for _, size := range sizes { + for _, threads := range threadsList { + matrixA := util.CreateMatrix(size) + matrixB := util.CreateMatrix(size) + + start := time.Now() + _ = multiplyMatricesParallel(matrixA, matrixB, threads) + elapsed := time.Since(start) + + fmt.Printf("Parallel multiplication of matrix %sx%s with %d threads took %s\n", strconv.Itoa(size), strconv.Itoa(size), threads, elapsed) + } + } +} + +func main() { + // Список размерностей матриц + sizes := []int{100, 300, 500} + + // Список количества потоков для тестирования + threadsList := []int{2, 4, 6, 8} + + // Запуск бенчмарка + benchmarkMatrixMultiplication(sizes, threadsList) +} diff --git a/zhimolostnova_anna_lab_5/regular.go b/zhimolostnova_anna_lab_5/regular.go new file mode 100644 index 0000000..2a4d43b --- /dev/null +++ b/zhimolostnova_anna_lab_5/regular.go @@ -0,0 +1,45 @@ +package main + +import ( + "fmt" + "strconv" + "time" + "zhimolostnova_anna_lab_5/util" +) + +// Последовательное умножение двух квадратных матриц +func multiplyMatricesSequential(a, b [][]int) [][]int { + size := len(a) + result := make([][]int, size) + for i := range result { + result[i] = make([]int, size) + for j := 0; j < size; j++ { + for k := 0; k < size; k++ { + result[i][j] += a[i][k] * b[k][j] + } + } + } + return result +} + +// Функция для бенчмарка последовательного умножения +func benchmarkMatrixMultiplicationSequential(sizes []int) { + for _, size := range sizes { + matrixA := util.CreateMatrix(size) + matrixB := util.CreateMatrix(size) + + start := time.Now() + _ = multiplyMatricesSequential(matrixA, matrixB) + elapsed := time.Since(start) + + fmt.Printf("Sequential multiplication of matrix %sx%s took %s\n", strconv.Itoa(size), strconv.Itoa(size), elapsed) + } +} + +func main() { + // Список размерностей матриц + sizes := []int{100, 300, 500} + + // Запуск бенчмарка + benchmarkMatrixMultiplicationSequential(sizes) +} diff --git a/zhimolostnova_anna_lab_5/util/matrix.go b/zhimolostnova_anna_lab_5/util/matrix.go new file mode 100644 index 0000000..5162b41 --- /dev/null +++ b/zhimolostnova_anna_lab_5/util/matrix.go @@ -0,0 +1,17 @@ +package util + +import ( + "math/rand" +) + +// CreateMatrix Функция для создания квадратной матрицы заданного размера +func CreateMatrix(size int) [][]int { + matrix := make([][]int, size) + for i := range matrix { + matrix[i] = make([]int, size) + for j := range matrix[i] { + matrix[i][j] = rand.Intn(25) // Заполняем случайными числами от 0 до 25 + } + } + return matrix +}