Merge pull request 'lobashov_ivan_lab_5 is ready' (#440) from lobashov_ivan_lab_5 into main
Reviewed-on: #440
This commit was merged in pull request #440.
This commit is contained in:
140
lobashov_ivan_lab_5/Matrix.java
Normal file
140
lobashov_ivan_lab_5/Matrix.java
Normal file
@@ -0,0 +1,140 @@
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Matrix {
|
||||
|
||||
public static double[][] generateMatrix(int n) {
|
||||
Random rand = new Random();
|
||||
double[][] matrix = new double[n][n];
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
matrix[i][j] = rand.nextDouble() * 10;
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
public static double[][] multiplySequential(double[][] A, double[][] B) {
|
||||
int n = A.length;
|
||||
double[][] C = new double[n][n];
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
double sum = 0;
|
||||
for (int k = 0; k < n; k++) {
|
||||
sum += A[i][k] * B[k][j];
|
||||
}
|
||||
C[i][j] = sum;
|
||||
}
|
||||
}
|
||||
return C;
|
||||
}
|
||||
|
||||
public static double[][] multiplyParallel(double[][] A, double[][] B, int numThreads) throws InterruptedException {
|
||||
int n = A.length;
|
||||
double[][] C = new double[n][n];
|
||||
|
||||
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
|
||||
|
||||
int rowsPerThread = (n + numThreads - 1) / numThreads;
|
||||
|
||||
for (int t = 0; t < numThreads; t++) {
|
||||
final int startRow = t * rowsPerThread;
|
||||
final int endRow = Math.min(startRow + rowsPerThread, n);
|
||||
|
||||
executor.submit(() -> {
|
||||
for (int i = startRow; i < endRow; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
double sum = 0;
|
||||
for (int k = 0; k < n; k++) {
|
||||
sum += A[i][k] * B[k][j];
|
||||
}
|
||||
C[i][j] = sum;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(1, TimeUnit.HOURS);
|
||||
|
||||
return C;
|
||||
}
|
||||
|
||||
public static void runBenchmark(int size, int numThreads) throws InterruptedException {
|
||||
System.out.println("\n=== Размер матрицы: " + size + "x" + size + " ===");
|
||||
|
||||
System.out.println("Генерация матриц...");
|
||||
double[][] A = generateMatrix(size);
|
||||
double[][] B = generateMatrix(size);
|
||||
|
||||
System.out.println("Запуск последовательного алгоритма...");
|
||||
long startSeq = System.currentTimeMillis();
|
||||
double[][] C_seq = multiplySequential(A, B);
|
||||
long endSeq = System.currentTimeMillis();
|
||||
long seqTime = endSeq - startSeq;
|
||||
|
||||
System.out.println("Запуск параллельного алгоритма (" + numThreads + " потоков)...");
|
||||
long startPar = System.currentTimeMillis();
|
||||
double[][] C_par = multiplyParallel(A, B, numThreads);
|
||||
long endPar = System.currentTimeMillis();
|
||||
long parTime = endPar - startPar;
|
||||
|
||||
double speedup = (double) seqTime / parTime;
|
||||
double efficiency = (speedup / numThreads) * 100;
|
||||
|
||||
System.out.println("Результаты:");
|
||||
System.out.println(" Последовательное умножение: " + seqTime + " мс");
|
||||
System.out.println(" Параллельное умножение: " + parTime + " мс");
|
||||
System.out.printf(" Ускорение: %.2fx%n", speedup);
|
||||
System.out.printf(" Эффективность: %.1f%%%n", efficiency);
|
||||
}
|
||||
|
||||
public static void runThreadScalingBenchmark(int size) throws InterruptedException {
|
||||
|
||||
|
||||
double[][] A = generateMatrix(size);
|
||||
double[][] B = generateMatrix(size);
|
||||
|
||||
long startSeq = System.currentTimeMillis();
|
||||
multiplySequential(A, B);
|
||||
long endSeq = System.currentTimeMillis();
|
||||
long seqTime = endSeq - startSeq;
|
||||
|
||||
System.out.println("Последовательное время: " + seqTime + " мс");
|
||||
|
||||
int[] threadCounts = {1, 2, 4, 8, 16};
|
||||
|
||||
for (int threads : threadCounts) {
|
||||
long startPar = System.currentTimeMillis();
|
||||
multiplyParallel(A, B, threads);
|
||||
long endPar = System.currentTimeMillis();
|
||||
long parTime = endPar - startPar;
|
||||
|
||||
double speedup = (double) seqTime / parTime;
|
||||
double efficiency = (speedup / threads) * 100;
|
||||
|
||||
System.out.printf(" %2d потоков: %5d мс, ускорение: %5.2fx, эффективность: %5.1f%%%n",
|
||||
threads, parTime, speedup, efficiency);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
System.out.println("Бенчмарк умножения матриц");
|
||||
System.out.println("==========================");
|
||||
|
||||
int[] sizes = {100, 300, 500};
|
||||
int defaultThreads = 4;
|
||||
|
||||
System.out.println("\nОсновные бенчмарки:");
|
||||
for (int size : sizes) {
|
||||
runBenchmark(size, defaultThreads);
|
||||
}
|
||||
|
||||
runThreadScalingBenchmark(500);
|
||||
|
||||
System.out.println("\nВсе бенчмарки выполнены.");
|
||||
}
|
||||
}
|
||||
68
lobashov_ivan_lab_5/README.md
Normal file
68
lobashov_ivan_lab_5/README.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Лабораторная работа 5
|
||||
**Тема**: Параллельное и последовательное умножение матриц на Java
|
||||
|
||||
# Технологии
|
||||
Для лабораторной работы использовались следующие технологии:
|
||||
1. Java 17 (Язык программированя)
|
||||
2. java.util.concurrent (для многопоточности)
|
||||
# Что делает программа
|
||||
Программа реализует два алгоритма умножения квадратных матриц:
|
||||
* Последовательный алгоритм - классическое тройное вложенное циклы
|
||||
* Параллельный алгоритм - распределение строк матрицы между потоками
|
||||
Ключевые особенности реализации:
|
||||
* Распределение строк матрицы между потоками равномерно
|
||||
* Использование ExecutorService для управления потоками
|
||||
* Автоматическая генерация тестовых матриц
|
||||
* Измерение времени выполнения и расчет эффективности
|
||||
|
||||
# Тесты
|
||||
В программе используются бенчмарки и 4 потока в параллельном алгоритме
|
||||
```
|
||||
int[] sizes = {100, 300, 500};
|
||||
int numThreads = 4
|
||||
```
|
||||
можно изменять размеры матриц и количество потоков
|
||||
```
|
||||
int[] sizes = {200, 400, 600};
|
||||
int numThreads = 2
|
||||
```
|
||||
# Сравнение результатов
|
||||
1. Матрица 100x100 :
|
||||
|
||||
Последовательное умножение: 3 мс
|
||||
|
||||
Параллельное умножение: 20 мс
|
||||
|
||||
Ускорение: 0,15x
|
||||
|
||||
Эффективность: 3,8%
|
||||
|
||||
* Вывод: Для небольших матриц накладные расходы на создание и синхронизацию потоков превышают выгоду от параллелизации. Время запуска потоков и управления ими становится доминирующим фактором.
|
||||
|
||||
2. Матрица 300х300:
|
||||
|
||||
Последовательное умножение: 28 мс
|
||||
|
||||
Параллельное умножение: 9 мс
|
||||
|
||||
Ускорение: 3,11x
|
||||
|
||||
Эффективность: 77,8%
|
||||
|
||||
* Вывод: При размере 300×300 параллельный алгоритм показывает хорошее ускорение с высокой эффективностью использования потоков.
|
||||
|
||||
3. Матрица 500х500:
|
||||
|
||||
Последовательное умножение: 138 мс
|
||||
|
||||
Параллельное умножение: 48 мс
|
||||
|
||||
Ускорение: 2,88x
|
||||
|
||||
Эффективность: 71,9%
|
||||
|
||||
* Вывод: Для больших матриц сохраняется значительное ускорение, хотя эффективность немного снижается из-за возрастающих затрат на синхронизацию.
|
||||
|
||||
**Заключение**: Параллельное умножение матриц демонстрирует значительное ускорение для больших матриц, однако требует тщательного выбора количества потоков и учета накладных расходов. Реализованный алгоритм эффективно распределяет вычислительную нагрузку и показывает хорошую масштабируемость для задач достаточного объема.
|
||||
# Ссылка на видео:
|
||||
[Видео](https://rutube.ru/video/private/84f875263c0ef2170d2a840e46f2fb71/?p=uizyfNcxTmOGglnnXwggSA)
|
||||
BIN
lobashov_ivan_lab_5/image.png
Normal file
BIN
lobashov_ivan_lab_5/image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
Reference in New Issue
Block a user