bondarenko_max_lab_6 #308
34
bondarenko_max_lab_6/README.md
Normal file
34
bondarenko_max_lab_6/README.md
Normal file
@ -0,0 +1,34 @@
|
||||
# Лабораторная работа 6 - Определение детерминанта матрицы с помощью параллельных вычислений
|
||||
### ПИбд-42 || Бондаренко Максим
|
||||
|
||||
# Описание работы
|
||||
|
||||
## Задание
|
||||
> [!NOTE]
|
||||
> Кратко: реализовать нахождение детерминанта квадратной матрицы.
|
||||
>
|
||||
> Подробно: в лабораторной работе требуется сделать два алгоритма: обычный и параллельный (задание со * - реализовать это в рамках одного алгоритма). В параллельном алгоритме предусмотреть ручное задание количества потоков (число потоков = 1 как раз и реализует задание со *), каждый из которых будет выполнять нахождение отдельной группы множителей.
|
||||
|
||||
## Краткое описание модулей и их работа
|
||||
1. matrix.operations.js
|
||||
- getMinor(matrix, row, col): Получает минор матрицы для заданной строки и столбца.
|
||||
- determinant(matrix): Вычисляет детерминант матрицы рекурсивно (последовательный алгоритм).
|
||||
- determinantParallel(matrix, numThreads): Вычисляет детерминант матрицы параллельно, распределяя задачи по заданному количеству потоков.
|
||||
|
||||
2. det.worker.js
|
||||
- Получает данные о своей части работы (миноры и знаки) и вычисляет частичный детерминант, который затем отправляет обратно главному потоку.
|
||||
|
||||
3. benchmark.js
|
||||
- generateMatrix(size): Генерирует случайную квадратную матрицу заданного размера.
|
||||
- benchmark(): Выполняет бенчмарки для матриц различных размеров, сравнивая время выполнения последовательного и параллельного алгоритмов с различным количеством потоков.
|
||||
|
||||
## Запуск
|
||||
```
|
||||
node benchmark.js
|
||||
```
|
||||
|
||||
## Результат работы
|
||||
> [!IMPORTANT]
|
||||
> ![benchmark.png](./benchmark.png)
|
||||
|
||||
Ссылка на видео: https://cloud.mail.ru/public/9Bky/mjwK7bqBL
|
37
bondarenko_max_lab_6/benchmark.js
Normal file
37
bondarenko_max_lab_6/benchmark.js
Normal file
@ -0,0 +1,37 @@
|
||||
const { determinant, determinantParallel } = require('./matrix.operations');
|
||||
|
||||
function generateMatrix(size) {
|
||||
const matrix = new Array(size);
|
||||
for (let i = 0; i < size; i++) {
|
||||
matrix[i] = new Array(size);
|
||||
for (let j = 0; j < size; j++) {
|
||||
matrix[i][j] = Math.floor(Math.random() * 20) - 10;
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
async function benchmark() {
|
||||
const sizes = [5, 7, 10];
|
||||
const numThreads = [2, 4, 8];
|
||||
|
||||
for (const size of sizes) {
|
||||
const matrix = generateMatrix(size);
|
||||
|
||||
console.log(`\nМатрица (${size}x${size}):`);
|
||||
|
||||
console.time('Последовательно');
|
||||
const detSeq = determinant(matrix);
|
||||
console.timeEnd('Последовательно');
|
||||
console.log(`Детерминант: ${detSeq}`);
|
||||
|
||||
for (const threads of numThreads) {
|
||||
console.time(`Параллельно (${threads} потоков)`);
|
||||
const detPar = await determinantParallel(matrix, threads);
|
||||
console.timeEnd(`Параллельно (${threads} потоков)`);
|
||||
console.log(`Детерминант: ${detPar}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
benchmark();
|
BIN
bondarenko_max_lab_6/benchmark.png
Normal file
BIN
bondarenko_max_lab_6/benchmark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
8
bondarenko_max_lab_6/det.worker.js
Normal file
8
bondarenko_max_lab_6/det.worker.js
Normal file
@ -0,0 +1,8 @@
|
||||
const { parentPort, workerData } = require('worker_threads');
|
||||
const { determinant } = require('./matrix.operations');
|
||||
|
||||
const partialDet = workerData.reduce((acc, job) => {
|
||||
return acc + job.value * determinant(job.minor) * job.sign;
|
||||
}, 0);
|
||||
|
||||
parentPort.postMessage(partialDet);
|
60
bondarenko_max_lab_6/matrix.operations.js
Normal file
60
bondarenko_max_lab_6/matrix.operations.js
Normal file
@ -0,0 +1,60 @@
|
||||
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
|
||||
|
||||
function getMinor(matrix, row, col) {
|
||||
return matrix
|
||||
.filter((_, i) => i !== row)
|
||||
.map(row => row.filter((_, j) => j !== col));
|
||||
}
|
||||
|
||||
function determinant(matrix) {
|
||||
const n = matrix.length;
|
||||
if (n === 1) return matrix[0][0];
|
||||
if (n === 2) return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
|
||||
|
||||
let det = 0;
|
||||
for (let j = 0; j < n; j++) {
|
||||
det += matrix[0][j] * determinant(getMinor(matrix, 0, j)) * (j % 2 === 0 ? 1 : -1);
|
||||
}
|
||||
return det;
|
||||
}
|
||||
|
||||
function determinantParallel(matrix, numThreads) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const n = matrix.length;
|
||||
if (n === 1) return resolve(matrix[0][0]);
|
||||
if (n === 2) return resolve(matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]);
|
||||
|
||||
let det = 0;
|
||||
let completed = 0;
|
||||
const jobs = [];
|
||||
|
||||
for (let j = 0; j < n; j++) {
|
||||
const sign = j % 2 === 0 ? 1 : -1;
|
||||
const minor = getMinor(matrix, 0, j);
|
||||
jobs.push({ minor, sign, value: matrix[0][j] });
|
||||
}
|
||||
|
||||
const chunkSize = Math.ceil(jobs.length / numThreads);
|
||||
const results = Array(numThreads).fill(0);
|
||||
|
||||
for (let i = 0; i < numThreads; i++) {
|
||||
const chunk = jobs.slice(i * chunkSize, (i + 1) * chunkSize);
|
||||
const worker = new Worker('./det.worker.js', { workerData: chunk });
|
||||
|
||||
worker.on('message', (partialDet) => {
|
||||
results[i] = partialDet;
|
||||
completed++;
|
||||
if (completed === numThreads) {
|
||||
resolve(results.reduce((acc, val) => acc + val, 0));
|
||||
}
|
||||
});
|
||||
|
||||
worker.on('error', reject);
|
||||
worker.on('exit', (code) => {
|
||||
if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { determinant, determinantParallel };
|
Loading…
Reference in New Issue
Block a user