abakarov_arslan_lab_1
abakarov_arslan_lab_1
This commit is contained in:
BIN
abakarov_arslan_lab_1/Diagrama.png
Normal file
BIN
abakarov_arslan_lab_1/Diagrama.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
63
abakarov_arslan_lab_1/ForkJoinMatrixDivider.java
Normal file
63
abakarov_arslan_lab_1/ForkJoinMatrixDivider.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import java.util.concurrent.RecursiveAction;
|
||||||
|
import java.util.concurrent.ForkJoinPool;
|
||||||
|
|
||||||
|
public class ForkJoinMatrixDivider {
|
||||||
|
public static void divideMatrix(int[][] matrix) {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
int max = findMax(matrix);
|
||||||
|
ForkJoinPool pool = new ForkJoinPool();
|
||||||
|
pool.invoke(new DivideTask(matrix, 0, matrix.length, max));
|
||||||
|
pool.shutdown();
|
||||||
|
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
System.out.println("ForkJoinPool: " + (endTime - startTime) + "ms");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DivideTask extends RecursiveAction {
|
||||||
|
private final int[][] matrix;
|
||||||
|
private final int start;
|
||||||
|
private final int end;
|
||||||
|
private final int max;
|
||||||
|
|
||||||
|
DivideTask(int[][] matrix, int start, int end, int max) {
|
||||||
|
this.matrix = matrix;
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void compute() {
|
||||||
|
if (end - start <= 10) { // porog
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
for (int j = 0; j < matrix[i].length; j++) {
|
||||||
|
matrix[i][j] /= max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int mid = (start + end) / 2;
|
||||||
|
DivideTask left = new DivideTask(matrix, start, mid, max);
|
||||||
|
DivideTask right = new DivideTask(matrix, mid, end, max);
|
||||||
|
invokeAll(left, right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int findMax(int[][] matrix) {
|
||||||
|
int max = matrix[0][0];
|
||||||
|
for (int[] row : matrix) {
|
||||||
|
for (int value : row) {
|
||||||
|
if (value > max) {
|
||||||
|
max = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int[][] matrix = MatrixGenerator.generateMatrix(1000, 1000);
|
||||||
|
divideMatrix(matrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
14
abakarov_arslan_lab_1/MatrixGenerator.java
Normal file
14
abakarov_arslan_lab_1/MatrixGenerator.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class MatrixGenerator {
|
||||||
|
public static int[][] generateMatrix(int rows, int cols) {
|
||||||
|
int[][] matrix = new int[rows][cols];
|
||||||
|
Random random = new Random();
|
||||||
|
for (int i = 0; i < rows; i++) {
|
||||||
|
for (int j = 0; j < cols; j++) {
|
||||||
|
matrix[i][j] = i+j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
abakarov_arslan_lab_1/SingleThreadedMatrixDivider.java
Normal file
28
abakarov_arslan_lab_1/SingleThreadedMatrixDivider.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
public class SingleThreadedMatrixDivider {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
int[][] matrix = MatrixGenerator.generateMatrix(1000, 1000);
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
int max = findMax(matrix);
|
||||||
|
for (int i = 0; i < matrix.length; i++) {
|
||||||
|
for (int j = 0; j < matrix[i].length; j++) {
|
||||||
|
matrix[i][j] /= max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
System.out.println("Single-flow: " + (endTime - startTime) + "ms");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int findMax(int[][] matrix) {
|
||||||
|
int max = matrix[0][0];
|
||||||
|
for (int[] row : matrix) {
|
||||||
|
for (int value : row) {
|
||||||
|
if (value > max) {
|
||||||
|
max = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
abakarov_arslan_lab_1/ThreadPoolMatrixDivider.java
Normal file
48
abakarov_arslan_lab_1/ThreadPoolMatrixDivider.java
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class ThreadPoolMatrixDivider {
|
||||||
|
public static void divideMatrix(int[][] matrix, int numThreads) {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
int max = findMax(matrix);
|
||||||
|
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
|
||||||
|
|
||||||
|
for (int i = 0; i < matrix.length; i++) {
|
||||||
|
final int row = i;
|
||||||
|
executor.submit(() -> {
|
||||||
|
for (int j = 0; j < matrix[row].length; j++) {
|
||||||
|
matrix[row][j] /= max;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
executor.shutdown();
|
||||||
|
try {
|
||||||
|
executor.awaitTermination(1, TimeUnit.MINUTES);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
System.out.println("ThreadPoolExecutor: " + (endTime - startTime) + "ms");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int findMax(int[][] matrix) {
|
||||||
|
int max = matrix[0][0];
|
||||||
|
for (int[] row : matrix) {
|
||||||
|
for (int value : row) {
|
||||||
|
if (value > max) {
|
||||||
|
max = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int[][] matrix = MatrixGenerator.generateMatrix(1000, 1000);
|
||||||
|
divideMatrix(matrix, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
91
abakarov_arslan_lab_1/readme.md
Normal file
91
abakarov_arslan_lab_1/readme.md
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
Лабораторная работа №1
|
||||||
|
Разработка многопоточного приложения с использованием Java Concurrency согласно варианту задания.
|
||||||
|
|
||||||
|
Необходимо:
|
||||||
|
Разработать однопоточный вариант алгоритма и замерить время его работы.
|
||||||
|
Разработать параллельный вариант алгоритма с использованием ThreadPoolExecutor и замерить время его работы.
|
||||||
|
Разработать параллельный вариант алгоритма с использованием ForkJoinPoll и замерить время его работы.
|
||||||
|
!!!. Массив генерируется до работы всех вариантов алгоритмов. Все три алгоритма обрабатывают три одинаковых массива.
|
||||||
|
|
||||||
|
Вариант задания 1: Разделить элементы матрицы на наибольший элемент.
|
||||||
|
|
||||||
|
Как запустить лабораторную работу:
|
||||||
|
javac ForkJoinMatrixDivider.java компилирует исходный код java ForkJoinMatrixDivider команда запускает скомпилированный класс
|
||||||
|
javac SingleThreadedMatrixDivider.java компилирует исходный код java SingleThreadedMatrixDivider команда запускает скомпилированный класс
|
||||||
|
javac ThreadPoolMatrixDivider.java компилирует исходный код java ThreadPoolMatrixDivider команда запускает скомпилированный класс
|
||||||
|
|
||||||
|
|
||||||
|
Какие технологии использовали:
|
||||||
|
Java 17+
|
||||||
|
|
||||||
|
ExecutorService (ThreadPoolExecutor)
|
||||||
|
|
||||||
|
ForkJoinPool
|
||||||
|
|
||||||
|
System.currentTimeMillis() для замеров времени выполнения
|
||||||
|
|
||||||
|
Как работает программа:
|
||||||
|
Генерация матрицы:
|
||||||
|
|
||||||
|
Программа создаёт двумерный массив заданного размера.
|
||||||
|
|
||||||
|
Заполняет его случайными значениями.
|
||||||
|
|
||||||
|
Определяет наибольший элемент матрицы.
|
||||||
|
|
||||||
|
Однопоточный алгоритм:
|
||||||
|
|
||||||
|
Проходит по всей матрице в одном потоке.
|
||||||
|
|
||||||
|
Делит каждый элемент матрицы на наибольший элемент.
|
||||||
|
|
||||||
|
Записывает результат в новую матрицу.
|
||||||
|
|
||||||
|
Измеряет время выполнения.
|
||||||
|
|
||||||
|
Параллельный алгоритм с ThreadPoolExecutor:
|
||||||
|
|
||||||
|
Создаёт пул потоков с фиксированным количеством потоков (обычно равное количеству ядер CPU).
|
||||||
|
|
||||||
|
Делит матрицу на строки, назначая обработку каждой строки отдельному потоку.
|
||||||
|
|
||||||
|
Потоки выполняют деление элементов и записывают результаты.
|
||||||
|
|
||||||
|
Ожидает завершения всех потоков.
|
||||||
|
|
||||||
|
Измеряет время выполнения.
|
||||||
|
|
||||||
|
Параллельный алгоритм с ForkJoinPool:
|
||||||
|
|
||||||
|
Использует принцип рекурсивного разбиения задач (Fork/Join).
|
||||||
|
|
||||||
|
Разбивает матрицу на более мелкие подзадачи, пока они не станут достаточно малы для обработки в одном потоке.
|
||||||
|
|
||||||
|
Выполняет деление элементов параллельно.
|
||||||
|
|
||||||
|
Объединяет результаты.
|
||||||
|
|
||||||
|
Измеряет время выполнения.
|
||||||
|
|
||||||
|
Вывод результатов:
|
||||||
|
|
||||||
|
Для каждого метода измеряется время выполнения.
|
||||||
|
|
||||||
|
Результаты выводятся в консоль.
|
||||||
|
|
||||||
|
(Размер матрицы 1000х1000)
|
||||||
|
Single thread alghoritm: 51 ms
|
||||||
|
ThreadPoolExecutor: 150 ms
|
||||||
|
ForkJoinPool: 90 ms
|
||||||
|
(Размер матрицы 2000х2000)
|
||||||
|
Single thread alghoritm: 242 ms
|
||||||
|
ThreadPoolExecutor: 300 ms
|
||||||
|
ForkJoinPool: 139 ms.
|
||||||
|
(Размер матрицы 3000x3000)
|
||||||
|
Single thread alghoritm: 452 ms
|
||||||
|
ThreadPoolExecutor: 495 ms
|
||||||
|
ForkJoinPool: 411 ms
|
||||||
|
|
||||||
|
|
||||||
|
Вывод
|
||||||
|
Использование ForkJoinPool демонстрирует наивысшую эффективность среди многопоточных подходов в этом алгоритме. ThreadPoolExecutor оказывается самым невыгодным из-за значительных накладных расходов, связанных с управлением потоками. Однопоточный метод работает достаточно хорошо на небольших объемах данных, однако с ростом вычислительной нагрузки он существенно уступает ForkJoinPool.
|
||||||
Reference in New Issue
Block a user