Merge pull request 'bondarenko_max_lab_6' (#308) from bondarenko_max_lab_6 into main
Reviewed-on: #308
This commit is contained in:
commit
9485011484
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