diff --git a/senkin_alexander_lab_5/.gitignore b/senkin_alexander_lab_5/.gitignore new file mode 100644 index 0000000..e0a1c00 --- /dev/null +++ b/senkin_alexander_lab_5/.gitignore @@ -0,0 +1 @@ +./idea \ No newline at end of file diff --git a/senkin_alexander_lab_5/README.md b/senkin_alexander_lab_5/README.md new file mode 100644 index 0000000..0e60baa --- /dev/null +++ b/senkin_alexander_lab_5/README.md @@ -0,0 +1,30 @@ +# Лабораторная работа №5 - Параллельное умножение матриц + +Цель: реализовать умножение двух больших квадратных матриц. + +Задача: в лабораторной работе требуется сделать два алгоритма: обычный и параллельный (задание со * - реализовать это в рамках одного алгоритма). В параллельном алгоритме предусмотреть ручное задание количества потоков (число потоков = 1 как раз и реализует задание со *), каждый из которых будет выполнять умножение элементов матрицы в рамках своей зоны ответственности. + +# Разработка приложения + +Было решено производить разработку приложения на языке Go, так как на нем удобно реализован механизм паралеллизма. +В рамках одного main файла реализованы две функции - параллельного и последовательного умножения матриц. Также реализована функция по запуску этих функций, и функция создания случайной матрицы. + +![img.png](img.png) + +# Запуск + +Запуск программы производится с помощью команды в командной строке go run {путь до исполняемого main.go файла} + +# Работа программы + +- Создание случайной матрицы: ![img_1.png](img_1.png) +- Метод для последовательного умножения матриц: ![img_2.png](img_2.png) +- Метод параллельного умножения матриц: ![img_3.png](img_3.png) +- Метод запуска тестов: ![img_4.png](img_4.png) +- Главный метод запуска программы main: ![img_5.png](img_5.png) +- Вывод на консоль и анализ результатов: ![img_6.png](img_6.png) +- По результатам видим, что на Go параллельное умножение матриц всегда выигрывает последовательное, и чем больше матрица и больше потоков, тем больше выигрыш по производительности + +# Видео + +Видео с разбором лабораторной работы - \ No newline at end of file diff --git a/senkin_alexander_lab_5/go.mod b/senkin_alexander_lab_5/go.mod new file mode 100644 index 0000000..59ddea4 --- /dev/null +++ b/senkin_alexander_lab_5/go.mod @@ -0,0 +1,3 @@ +module DAS_2023_1/senkin_alexander_lab_5 + +go 1.21.4 diff --git a/senkin_alexander_lab_5/img.png b/senkin_alexander_lab_5/img.png new file mode 100644 index 0000000..287f1c6 Binary files /dev/null and b/senkin_alexander_lab_5/img.png differ diff --git a/senkin_alexander_lab_5/img_1.png b/senkin_alexander_lab_5/img_1.png new file mode 100644 index 0000000..6d8d3b5 Binary files /dev/null and b/senkin_alexander_lab_5/img_1.png differ diff --git a/senkin_alexander_lab_5/img_2.png b/senkin_alexander_lab_5/img_2.png new file mode 100644 index 0000000..54799f1 Binary files /dev/null and b/senkin_alexander_lab_5/img_2.png differ diff --git a/senkin_alexander_lab_5/img_3.png b/senkin_alexander_lab_5/img_3.png new file mode 100644 index 0000000..c53bff7 Binary files /dev/null and b/senkin_alexander_lab_5/img_3.png differ diff --git a/senkin_alexander_lab_5/img_4.png b/senkin_alexander_lab_5/img_4.png new file mode 100644 index 0000000..17bfe82 Binary files /dev/null and b/senkin_alexander_lab_5/img_4.png differ diff --git a/senkin_alexander_lab_5/img_5.png b/senkin_alexander_lab_5/img_5.png new file mode 100644 index 0000000..a853e6b Binary files /dev/null and b/senkin_alexander_lab_5/img_5.png differ diff --git a/senkin_alexander_lab_5/img_6.png b/senkin_alexander_lab_5/img_6.png new file mode 100644 index 0000000..29b9c0d Binary files /dev/null and b/senkin_alexander_lab_5/img_6.png differ diff --git a/senkin_alexander_lab_5/main/main.go b/senkin_alexander_lab_5/main/main.go new file mode 100644 index 0000000..8d28975 --- /dev/null +++ b/senkin_alexander_lab_5/main/main.go @@ -0,0 +1,92 @@ +package main + +import ( + "fmt" + "math/rand" + "sync" + "time" +) + +func sequentialMatrixMultiply(matrixA, matrixB [][]float64) [][]float64 { + rowsA, colsA := len(matrixA), len(matrixA[0]) + colsB := len(matrixB[0]) + result := make([][]float64, rowsA) + for i := range result { + result[i] = make([]float64, colsB) + } + + for i := 0; i < rowsA; i++ { + for j := 0; j < colsB; j++ { + for k := 0; k < colsA; k++ { + result[i][j] += matrixA[i][k] * matrixB[k][j] + } + } + } + return result +} + +func parallelMatrixMultiply(matrixA, matrixB [][]float64, numProcesses int) [][]float64 { + rowsA, colsA := len(matrixA), len(matrixA[0]) + colsB := len(matrixB[0]) + result := make([][]float64, rowsA) + for i := range result { + result[i] = make([]float64, colsB) + } + + var wg sync.WaitGroup + wg.Add(numProcesses) + + for i := 0; i < numProcesses; i++ { + go func(id, startRow, endRow int) { + defer wg.Done() + for i := startRow; i < endRow; i++ { + for j := 0; j < colsB; j++ { + for k := 0; k < colsA; k++ { + result[i][j] += matrixA[i][k] * matrixB[k][j] + } + } + } + }(i, i*rowsA/numProcesses, (i+1)*rowsA/numProcesses) + } + + wg.Wait() + return result +} + +func runTest(matrixSize, numProcesses int) { + matrixA := generateRandomMatrix(matrixSize, matrixSize) + matrixB := generateRandomMatrix(matrixSize, matrixSize) + + startTime := time.Now() + _ = sequentialMatrixMultiply(matrixA, matrixB) + sequentialTime := time.Since(startTime) + fmt.Printf("Sequential matrix multiplication took (%dx%d): %s\n", matrixSize, matrixSize, sequentialTime) + + startTime = time.Now() + _ = parallelMatrixMultiply(matrixA, matrixB, numProcesses) + parallelTime := time.Since(startTime) + fmt.Printf("Parallel matrix multiplication with %d threads took (%dx%d): %s\n", numProcesses, matrixSize, matrixSize, parallelTime) +} + +func generateRandomMatrix(rows, cols int) [][]float64 { + matrix := make([][]float64, rows) + for i := range matrix { + matrix[i] = make([]float64, cols) + for j := range matrix[i] { + matrix[i][j] = rand.Float64() + } + } + return matrix +} + +func main() { + rand.Seed(time.Now().UnixNano()) + + // Benchmarks for matrices with sizes 100x100, 300x300, and 500x500 with different numbers of processes + runTest(100, 2) + runTest(100, 4) + runTest(300, 2) + runTest(300, 4) + runTest(500, 2) + runTest(500, 4) +}