khaliullov_ramil_lab_1 is ready
This commit is contained in:
95
khaliullov_ramil_lab_1/MatrixNormalization.java
Normal file
95
khaliullov_ramil_lab_1/MatrixNormalization.java
Normal file
@@ -0,0 +1,95 @@
|
||||
import java.util.Random;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class MatrixNormalization {
|
||||
private static int SIZE;
|
||||
private static final int THREADS = Runtime.getRuntime().availableProcessors();
|
||||
private static double[][] matrix;
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
System.out.print("Enter the size of the matrix: ");
|
||||
SIZE = scanner.nextInt();
|
||||
matrix = new double[SIZE][SIZE];
|
||||
|
||||
generateMatrix();
|
||||
System.out.println("Matrix generated.......");
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
normalizeSingleThread();
|
||||
long endTime = System.nanoTime();
|
||||
System.out.println("Single-threaded time: " + (endTime - startTime) / 1_000_000 + " ms");
|
||||
|
||||
generateMatrix();
|
||||
ExecutorService executor = Executors.newFixedThreadPool(THREADS);
|
||||
startTime = System.nanoTime();
|
||||
normalizeThreadPool(executor);
|
||||
endTime = System.nanoTime();
|
||||
System.out.println("ThreadPoolExecutor time: " + (endTime - startTime) / 1_000_000 + " ms");
|
||||
executor.shutdown();
|
||||
|
||||
generateMatrix();
|
||||
ForkJoinPool forkJoinPool = new ForkJoinPool(THREADS);
|
||||
startTime = System.nanoTime();
|
||||
forkJoinPool.invoke(new ForkJoinNormalize(0, SIZE));
|
||||
endTime = System.nanoTime();
|
||||
System.out.println("ForkJoinPool time: " + (endTime - startTime) / 1_000_000 + " ms");
|
||||
}
|
||||
|
||||
private static void generateMatrix() {
|
||||
Random rand = new Random();
|
||||
for (int i = 0; i < SIZE; i++)
|
||||
for (int j = 0; j < SIZE; j++)
|
||||
matrix[i][j] = rand.nextDouble() * 100;
|
||||
}
|
||||
|
||||
private static double findMax() {
|
||||
double max = Double.MIN_VALUE;
|
||||
for (double[] row : matrix)
|
||||
for (double val : row)
|
||||
max = Math.max(max, val);
|
||||
return max;
|
||||
}
|
||||
|
||||
private static void normalizeSingleThread() {
|
||||
double max = findMax();
|
||||
for (int i = 0; i < SIZE; i++)
|
||||
for (int j = 0; j < SIZE; j++)
|
||||
matrix[i][j] /= max;
|
||||
}
|
||||
|
||||
private static void normalizeThreadPool(ExecutorService executor) {
|
||||
double max = findMax();
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
final int row = i;
|
||||
executor.submit(() -> {
|
||||
for (int j = 0; j < SIZE; j++)
|
||||
matrix[row][j] /= max;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static class ForkJoinNormalize extends RecursiveAction {
|
||||
private static final int THRESHOLD = 100;
|
||||
private final int start, end;
|
||||
|
||||
ForkJoinNormalize(int start, int end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compute() {
|
||||
double max = findMax();
|
||||
if (end - start <= THRESHOLD) {
|
||||
for (int i = start; i < end; i++)
|
||||
for (int j = 0; j < SIZE; j++)
|
||||
matrix[i][j] /= max;
|
||||
} else {
|
||||
int mid = (start + end) / 2;
|
||||
invokeAll(new ForkJoinNormalize(start, mid), new ForkJoinNormalize(mid, end));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
119
khaliullov_ramil_lab_1/README.md
Normal file
119
khaliullov_ramil_lab_1/README.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# **Лабораторная работа №1**
|
||||
|
||||
## **Тема:** Разработка многопоточного приложения с использованием Java Concurrency
|
||||
|
||||
### **Цель работы:**
|
||||
Разработка многопоточного приложения с использованием Java Concurrency согласно варианту задания.
|
||||
Необходимо:
|
||||
1. Разработать однопоточный вариант алгоритма и замерить время его работы.
|
||||
2. Разработать параллельный вариант алгоритма с использованием ThreadPoolExecutor и замерить время его работы
|
||||
3. Разработать параллельный вариант алгоритма с использованием ForkJoinPoll и замерить время его работы.
|
||||
ВАЖНО: Массив генерируется до работы всех вариантов алгоритмов. Все три алгоритма обрабатывают три одинаковых массива.
|
||||
|
||||
---
|
||||
### **Вариант:**
|
||||
1 Разделить элементы матрицы на наибольший элемент.
|
||||
|
||||
---
|
||||
### **Шаги для запуска:**
|
||||
1. Перейти в директорию с исходными файлами.
|
||||
2. Скомпилировать Java-код:
|
||||
```sh
|
||||
javac MatrixNormalization.java
|
||||
```
|
||||
3. Запустить программу:
|
||||
```sh
|
||||
java MatrixNormalization
|
||||
```
|
||||
|
||||
---
|
||||
## **Используемые технологии:**
|
||||
- `java.util.concurrent` — инструменты для работы с многопоточностью (пулы потоков, синхронизация).
|
||||
- `ForkJoinPool` — пул потоков для выполнения параллельных задач.
|
||||
- `ExecutorService` – управление пулом потоков.
|
||||
- `RecursiveAction` — абстрактный класс из Fork/Join Framework, используемый для выполнения параллельных задач без возвращаемого результата.
|
||||
|
||||
---
|
||||
## **Код:**
|
||||
1. Однопоточный алгоритм:
|
||||
```java
|
||||
private static void normalizeSingleThread() {
|
||||
double max = findMax();
|
||||
for (int i = 0; i < SIZE; i++)
|
||||
for (int j = 0; j < SIZE; j++)
|
||||
matrix[i][j] /= max;
|
||||
}
|
||||
```
|
||||
2. ThreadPoolExecutor
|
||||
```java
|
||||
private static void normalizeThreadPool(ExecutorService executor) {
|
||||
double max = findMax();
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
final int row = i;
|
||||
executor.submit(() -> {
|
||||
for (int j = 0; j < SIZE; j++)
|
||||
matrix[row][j] /= max;
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
3. ForkJoinPoll
|
||||
```java
|
||||
static class ForkJoinNormalize extends RecursiveAction {
|
||||
private static final int THRESHOLD = 100;
|
||||
private final int start, end;
|
||||
|
||||
ForkJoinNormalize(int start, int end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compute() {
|
||||
double max = findMax();
|
||||
if (end - start <= THRESHOLD) {
|
||||
for (int i = start; i < end; i++)
|
||||
for (int j = 0; j < SIZE; j++)
|
||||
matrix[i][j] /= max;
|
||||
} else {
|
||||
int mid = (start + end) / 2;
|
||||
invokeAll(new ForkJoinNormalize(start, mid), new ForkJoinNormalize(mid, end));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
|
||||
## **Описание работы программы:**
|
||||
Программа создаёт квадратную матрицу **cols × rows** и выполняет нормализацию матрицы с использованием разных подходов к многопоточной обработке. Нормализация заключается в делении всех элементов матрицы на ее максимальный элемент.
|
||||
|
||||
---
|
||||
|
||||
## **Результаты работы:**
|
||||
1. Работа алгоритмов на матрице 100 на 100:
|
||||
```
|
||||
Время выполнения однопоточного алгоритма: 23 мс
|
||||
Время выполнения с потоками ThreadPoolExecutor: 22 мс
|
||||
Время выполнения с потоками ForkJoinPool: 16 мс
|
||||
```
|
||||
2. Работа алгоритмов на матрице 500 на 500:
|
||||
```
|
||||
Время выполнения однопоточного алгоритма: 76 мс
|
||||
Время выполнения с потоками ThreadPoolExecutor: 48 мс
|
||||
Время выполнения с потоками ForkJoinPool: 37 мс
|
||||
```
|
||||
|
||||
3. Работа алгоритмов на матрице 1000 на 1000:
|
||||
|
||||
```
|
||||
Время выполнения однопоточного алгоритма: 118 мс
|
||||
Время выполнения с потоками ThreadPoolExecutor: 82 мс
|
||||
Время выполнения с потоками ForkJoinPool: 70 мс
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **Вывод:**
|
||||
- При небольших матрицах многопоточные алгоритмы не дают значительных преимуществ из-за накладных расходов.
|
||||
- При увеличении размера матрицы многопоточные подходы заметно ускоряют вычисления.
|
||||
- ForkJoinPool эффективнее ThreadPoolExecutor за счет более гибкого механизма балансировки нагрузки.
|
||||
Reference in New Issue
Block a user