diff --git a/podkorytova_yulia_lab_5/README.md b/podkorytova_yulia_lab_5/README.md new file mode 100644 index 0000000..1b73b50 --- /dev/null +++ b/podkorytova_yulia_lab_5/README.md @@ -0,0 +1,62 @@ +# Лабораторная работа 5. Параллельное умножение матриц +### Задание на лабораторную работу +Кратко: реализовать умножение двух больших квадратных матриц. + +Подробно: в лабораторной работе требуется сделать два алгоритма: обычный и параллельный. В параллельном алгоритме предусмотреть ручное задание количества потоков, каждый из которых будет выполнять умножение элементов матрицы в рамках своей зоны ответственности. +*** +### Описание работы +Обычный алгоритм реализован в методе `multiplySequential`: +``` +public static int[][] multiplySequential(int[][] m1, int[][] m2) { + int size = m1.length; + int[][] res = new int[size][size]; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + for (int k = 0; k < size; k++) { + res[i][j] += m1[i][k] * m2[k][j]; + } + } + } + + return res; +} +``` +Параллельный алгоритм реализован в методе `multiplyParallel`: +``` +public static int[][] multiplyParallel(int[][] m1, int[][] m2, int threadCount) throws InterruptedException { + int size = m1.length; + int[][] res = new int[size][size]; + ExecutorService executor = Executors.newFixedThreadPool(threadCount); + for (int i = 0; i < size; i++) { + int r = i; + executor.submit(() -> { + for (int j = 0; j < size; j++) { + for (int k = 0; k < size; k++) { + res[r][j] += m1[r][k] * m2[k][j]; + } + } + }); + } + executor.shutdown(); + executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); + + return res; +} +``` +В методе создается пул потоков с помощью `ExecutorService` и указанным количеством потоков `threadCount`. +Затем для каждой строки матрицы m1, создается задача, которая будет выполняться параллельно в отдельном потоке. +Каждый поток берет на себя определенную строку матрицы m1 и умножает ее на соответствующие столбцы матрицы m2, результат умножения записывается в соответствующую ячейку результирующей матрицы res. +Так каждый поток работает над своей зоной ответственности в матрицах и выполняет умножение независимо от других потоков. + + +*** +### Результаты +***Результат работы*** +![](images/result.jpg) + +На матрицах размером 100x100 последовательный алгоритм справляется быстрее параллельного, а на матрицах размером 300x300 и 500x500 наоборот - параллельный алгоритм справляется быстрее последовательного. + +***Вывод:*** при небольших размерах матриц использование параллельного алгоритма дает проигрыш в производительности использованию последовательного алгоритма. Параллельное умножение матриц будет эффективнее, если размер матриц достаточно большой. + +### Ссылка на видео: +https://drive.google.com/file/d/1jnSD5FNua2payHZc3k18vfhxaAN31Q4A/view?usp=sharing \ No newline at end of file diff --git a/podkorytova_yulia_lab_5/app/src/Main.java b/podkorytova_yulia_lab_5/app/src/Main.java new file mode 100644 index 0000000..0f3a8b0 --- /dev/null +++ b/podkorytova_yulia_lab_5/app/src/Main.java @@ -0,0 +1,74 @@ +import java.util.Random; +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[] sizes = new int[] {100, 300, 500}; + for (int i = 0; i < sizes.length; i++) { + System.out.println("Время выполнения умножения двух матриц размером " + sizes[i] + "х" + sizes[i] + ":"); + int[][] m1 = generateMatrix(sizes[i]); + int[][] m2 = generateMatrix(sizes[i]); + + long start= System.currentTimeMillis(); + int[][] resultSequential = multiplySequential(m1, m2); + long end = System.currentTimeMillis(); + long sequentialTime = end - start; + System.out.println("Обычный (последовательный) алгоритм - " + sequentialTime + " мс"); + + int threadCount = 10; + start = System.currentTimeMillis(); + int[][] resultParallel = multiplyParallel(m1, m2, threadCount); + end = System.currentTimeMillis(); + long parallelTime = end - start; + System.out.println("Параллельный алгоритм c " + threadCount + " потоками - " + parallelTime + " мс\n"); + } + } + + public static int[][] generateMatrix(int size) { + int[][] m = new int[size][size]; + Random random = new Random(); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + m[i][j] = random.nextInt(100); + } + } + + return m; + } + + public static int[][] multiplySequential(int[][] m1, int[][] m2) { + int size = m1.length; + int[][] res = new int[size][size]; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + for (int k = 0; k < size; k++) { + res[i][j] += m1[i][k] * m2[k][j]; + } + } + } + + return res; + } + + public static int[][] multiplyParallel(int[][] m1, int[][] m2, int threadCount) throws InterruptedException { + int size = m1.length; + int[][] res = new int[size][size]; + ExecutorService executor = Executors.newFixedThreadPool(threadCount); + for (int i = 0; i < size; i++) { + int r = i; + executor.submit(() -> { + for (int j = 0; j < size; j++) { + for (int k = 0; k < size; k++) { + res[r][j] += m1[r][k] * m2[k][j]; + } + } + }); + } + executor.shutdown(); + executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); + + return res; + } +} \ No newline at end of file diff --git a/podkorytova_yulia_lab_5/images/result.JPG b/podkorytova_yulia_lab_5/images/result.JPG new file mode 100644 index 0000000..a822ae9 Binary files /dev/null and b/podkorytova_yulia_lab_5/images/result.JPG differ