Merge pull request 'afanasev_dmitry_lab_5 is ready' (#173) from afanasev_dmitry_lab_5 into main

Reviewed-on: #173
This commit is contained in:
Alexey 2024-11-29 15:46:43 +04:00
commit e01e3267c6
3 changed files with 180 additions and 0 deletions

View File

@ -0,0 +1,31 @@
# Лабораторная работа 5
## Описание
Задание заключается в реализации алгоритмов умножения больших квадратных матриц. Необходимо разработать два алгоритма: последовательный и параллельный. А также провести бенчмарки, а затем описать результаты в отчете.
**100x100 матрица**:
- **4 потока** — наилучший результат.
- **10 потоков** — медленнее на почти в половину.
- **6 и 8 потоков** — хуже 4 потоков.
- **1 и 2 потока** — значительно медленнее.
**300x300 матрица**:
- **4 потока** — лучший результат.
- **8 потоков** — чуть хуже.
- **10 потоков** — медленнее.
- **1 и 2 потока** — значительно медленнее.
**500x500 матрица**:
- **8 потоков** — лучший результат.
- **6 и 10 потоков** — немного хуже.
- **4 потока** — значительно медленнее.
- **1 поток** — самый медленный.
**Ссылка на демонстрацию работы программы**: https://vk.com/video215756667_456239455?list=ln-z7zFcpvxLexJd3f8ss
**Вывод**:
- Если операция сложнее, рост производительности происходит с увеличением числа потоков.
- Слишком много потоков увеличивает накладные расходы (например, 10 потоков). Это может быть связано, например, с:
1. **Переключением контекстов**: Когда потоков больше, чем ядер процессора, операционная система часто переключает контексты, что занимает время.
2. **Конкуренцией за ресурсы**: Много потоков конкурируют за ограниченные ресурсы, такие как процессорное время и кэш.
3. **Управлением потоками**: С увеличением числа потоков растёт нагрузка на систему, связанную с их созданием, управлением и завершением.

29
afanasev_dmitry_lab_5/main/.gitignore vendored Normal file
View File

@ -0,0 +1,29 @@
### IntelliJ IDEA ###
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

View File

@ -0,0 +1,120 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MatrixMultiplier {
private final int[][] matrixA;
private final int[][] matrixB;
private final int[][] result;
private final int size;
public MatrixMultiplier(int size) {
this.size = size;
this.matrixA = generateMatrix(size);
this.matrixB = generateMatrix(size);
this.result = new int[size][size];
}
private int[][] generateMatrix(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() * 10);
}
}
return matrix;
}
public void multiplySequential() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
for (int k = 0; k < size; k++) {
result[i][j] += matrixA[i][k] * matrixB[k][j];
}
}
}
}
public void multiplyParallel(int numThreads) throws InterruptedException {
if (numThreads == 1) {
multiplySequential();
return;
}
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
int chunkSize = (int) Math.ceil((double) size / numThreads);
for (int thread = 0; thread < numThreads; thread++) {
final int startRow = thread * chunkSize;
final int endRow = Math.min(startRow + chunkSize, size);
executor.submit(() -> {
for (int i = startRow; i < endRow; i++) {
for (int j = 0; j < size; j++) {
for (int k = 0; k < size; k++) {
result[i][j] += matrixA[i][k] * matrixB[k][j];
}
}
}
});
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
private void resetResult() {
for (int i = 0; i < size; i++) {
Arrays.fill(result[i], 0);
}
}
static class Result {
int threads;
long time;
Result(int threads, long time) {
this.threads = threads;
this.time = time;
}
}
public static void main(String[] args) throws InterruptedException {
int[] matrixSizes = {100, 300, 500};
int[] threadCounts = {1, 2, 4, 6, 8, 10};
int runs = 5; // количество прогонов
for (int size : matrixSizes) {
System.out.println("\nРазмер матрицы: " + size + "x" + size);
MatrixMultiplier multiplier = new MatrixMultiplier(size);
List<Result> results = new ArrayList<>();
for (int threads : threadCounts) {
long totalDuration = 0;
for (int run = 0; run < runs; run++) {
multiplier.resetResult();
long startTime = System.nanoTime();
multiplier.multiplyParallel(threads);
long endTime = System.nanoTime();
totalDuration += (endTime - startTime);
}
long averageDuration = totalDuration / runs;
results.add(new Result(threads, averageDuration));
}
// Сортировка по времени выполнения
results.sort(Comparator.comparingLong(r -> r.time));
System.out.println("Результаты (среднее время за " + runs + " прогонов):");
for (Result result : results) {
System.out.printf("Потоки: %d, среднее время: %d нс\n", result.threads, result.time);
}
}
}
}