diff --git a/kutygin_andrey_lab_5/.idea/.gitignore b/kutygin_andrey_lab_5/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/kutygin_andrey_lab_5/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/kutygin_andrey_lab_5/.idea/jpa-buddy.xml b/kutygin_andrey_lab_5/.idea/jpa-buddy.xml new file mode 100644 index 0000000..966d5f5 --- /dev/null +++ b/kutygin_andrey_lab_5/.idea/jpa-buddy.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/kutygin_andrey_lab_5/.idea/misc.xml b/kutygin_andrey_lab_5/.idea/misc.xml new file mode 100644 index 0000000..cac8158 --- /dev/null +++ b/kutygin_andrey_lab_5/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/kutygin_andrey_lab_5/.idea/modules.xml b/kutygin_andrey_lab_5/.idea/modules.xml new file mode 100644 index 0000000..03803f6 --- /dev/null +++ b/kutygin_andrey_lab_5/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/kutygin_andrey_lab_5/README.md b/kutygin_andrey_lab_5/README.md new file mode 100644 index 0000000..63781e7 --- /dev/null +++ b/kutygin_andrey_lab_5/README.md @@ -0,0 +1,62 @@ +## Задание +Кратко: реализовать умножение двух больших квадратных матриц. + +Подробно: в лабораторной работе требуется сделать два алгоритма: обычный и параллельный. В параллельном алгоритме предусмотреть ручное задание количества потоков, каждый из которых будет выполнять умножение элементов матрицы в рамках своей зоны ответственности. + +### Ход работы +**Последовательный алгоритм** + +public static int[][] multiplyMatricesSequential(int[][] matrix1, int[][] matrix2) { + +int rows1 = matrix1.length; + +int columns1 = matrix1[0].length; + +int columns2 = matrix2[0].length; + + var matrixResult = new int[size][size]; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + for (int m = 0; m < size; m++) { + matrixResult[i][j] += matrix1[i][m] * matrix2[m][j]; + } + } + } + return matrixResult; +Параллельный алгоритм +public static int[][] multiplyMatricesParallel(int[][] matrix1, int[][] matrix2) { +int rows1 = matrix1.length; +int columns1 = matrix1[0].length; +int columns2 = matrix2[0].length; + + var matrixResult = new int[size][size]; + + ExecutorService executorService = Executors.newFixedThreadPool(nThreads); + int blockSize = size / nThreads; + + for (int i = 0; i < nThreads; i++) { + int startRow = i * blockSize; + int endRow = (i + 1) * blockSize; + if (i == nThreads - 1) { + endRow = size; + } + + int finalEndRow = endRow; + executorService.submit(() -> { + for (int row = startRow; row < finalEndRow; row++) { + for (int col = 0; col < size; col++) { + for (int m = 0; m < size; m++) { + matrixResult[row][col] += matrix1[row][m] * matrix2[m][col]; + } + } + } + }); +Результат +Была проверка времени выполнения алгоритма для матриц размером 100х100, 300х300, 500х500 с разным количеством потоков. +![sreenshot](screen.png) + +Из данных скриншотов видно, что в случае с матрицей 100х100 последовательный алгоритм работает лучше, чем параллельный, в других случаях наоборот. + +Для остальных матриц параллельный алгоритм работает лучше, а также увеличение кол-ва потоков уменьшает время выполнения алгоритма. (хотя в случае матрицы 100х100 - сильно увеличивает) + +Видео: https://disk.yandex.ru/d/zeVdy1b0mC79cQ \ No newline at end of file diff --git a/kutygin_andrey_lab_5/lab5.iml b/kutygin_andrey_lab_5/lab5.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/kutygin_andrey_lab_5/lab5.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/kutygin_andrey_lab_5/out/production/lab5/Main.class b/kutygin_andrey_lab_5/out/production/lab5/Main.class new file mode 100644 index 0000000..79b7f97 Binary files /dev/null and b/kutygin_andrey_lab_5/out/production/lab5/Main.class differ diff --git a/kutygin_andrey_lab_5/screen.png b/kutygin_andrey_lab_5/screen.png new file mode 100644 index 0000000..28b5119 Binary files /dev/null and b/kutygin_andrey_lab_5/screen.png differ diff --git a/kutygin_andrey_lab_5/src/Main.java b/kutygin_andrey_lab_5/src/Main.java new file mode 100644 index 0000000..7a12ad8 --- /dev/null +++ b/kutygin_andrey_lab_5/src/Main.java @@ -0,0 +1,103 @@ +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +public class Main { + public static void main(String[] args) throws InterruptedException { + int nThreads = 8; + //100x100 + var matrix1 = Matrix(100); + var matrix2 = Matrix(100); + //Последовательный алгоритм + long startTime = System.currentTimeMillis(); + int[][] matrixResult = SequentialMult(matrix1, matrix2, matrix1.length); + long endTime = System.currentTimeMillis(); + System.out.println("sequentially, 100x100, exec time: " + (endTime - startTime) + " ms"); + //Параллельный алгоритм + startTime = System.currentTimeMillis(); + matrixResult = ParallelMult(matrix1, matrix2, matrix1.length, nThreads); + endTime = System.currentTimeMillis(); + System.out.println("parallel, 100x100, (" + nThreads + " flows), exec time : " + (endTime - startTime) + " ms\n"); + + //300x300 + matrix1 = Matrix(300); + matrix2 = Matrix(300); + //Последовательный алгоритм + startTime = System.currentTimeMillis(); + matrixResult = SequentialMult(matrix1, matrix2, matrix1.length); + endTime = System.currentTimeMillis(); + System.out.println("sequentially, 300x300, exec time: " + (endTime - startTime) + " ms"); + //Параллельный алгоритм + startTime = System.currentTimeMillis(); + matrixResult = ParallelMult(matrix1, matrix2, matrix1.length, nThreads); + endTime = System.currentTimeMillis(); + System.out.println("parallel, 300x300, (" + nThreads + " flows), exec time : " + (endTime - startTime) + " ms\n"); + + //500x500 + matrix1 = Matrix(500); + matrix2 = Matrix(500); + //Последовательный алгоритм + startTime = System.currentTimeMillis(); + matrixResult = SequentialMult(matrix1, matrix2, matrix1.length); + endTime = System.currentTimeMillis(); + System.out.println("sequentially, 500x500, exec time: " + (endTime - startTime) + " ms"); + //Параллельный алгоритм + startTime = System.currentTimeMillis(); + matrixResult = ParallelMult(matrix1, matrix2, matrix1.length, nThreads); + endTime = System.currentTimeMillis(); + System.out.println("parallel, 500x500, (" + nThreads + " flows), exec time : " + (endTime - startTime) + " ms\n"); + } + + public static int[][] Matrix(int size) { + int[][] matrix = new int[size][size]; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + matrix[i][j] = (int) (Math.random() * 1000); + } + } + return matrix; + } + + public static int[][] SequentialMult(int[][] matrix1, int[][] matrix2, int size) { + var matrixResult = new int[size][size]; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + for (int m = 0; m < size; m++) { + matrixResult[i][j] += matrix1[i][m] * matrix2[m][j]; + } + } + } + return matrixResult; + } + + public static int[][] ParallelMult(int[][] matrix1, int[][] matrix2, int size, int nThreads) throws InterruptedException { + var matrixResult = new int[size][size]; + + ExecutorService executorService = Executors.newFixedThreadPool(nThreads); + int blockSize = size / nThreads; + + for (int i = 0; i < nThreads; i++) { + int startRow = i * blockSize; + int endRow = (i + 1) * blockSize; + if (i == nThreads - 1) { + endRow = size; + } + + int finalEndRow = endRow; + executorService.submit(() -> { + for (int row = startRow; row < finalEndRow; row++) { + for (int col = 0; col < size; col++) { + for (int m = 0; m < size; m++) { + matrixResult[row][col] += matrix1[row][m] * matrix2[m][col]; + } + } + } + }); + } + + executorService.shutdown(); + executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); + + return matrixResult; + } +} \ No newline at end of file