diff --git a/bondarenko_max_lab_5/README.md b/bondarenko_max_lab_5/README.md new file mode 100644 index 0000000..07bd101 --- /dev/null +++ b/bondarenko_max_lab_5/README.md @@ -0,0 +1,38 @@ +# Лабораторная работа 5 - Вспоминаем математику или параллельное перемножение матриц +### ПИбд-42 || Бондаренко Максим + +# Описание работы + +## Задание +> [!NOTE] +> Кратко: реализовать умножение двух больших квадратных матриц. +> +> Подробно: в лабораторной работе требуется сделать два алгоритма: обычный и параллельный (задание со * - реализовать это в рамках одного алгоритма). В параллельном алгоритме предусмотреть ручное задание количества потоков (число потоков = 1 как раз и реализует задание со *), каждый из которых будет выполнять умножение элементов матрицы в рамках своей зоны ответственности. + +## Краткое описание модулей и их работа +1. matrix.operations.js +multiplyMatricesSequential(A, B): +- Перебирает элементы матриц и вычисляет их произведение, заполняя результирующую матрицу. +multiplyMatricesParallel(A, B, numThreads): +- Делит работу между потоками, каждый из которых умножает часть матриц. Запускает воркеры и собирает их результаты. +2. benchmark.js +generateMatrix(size): +- Создает матрицу с случайными значениями заданного размера. +benchmark(): +- Вызывает generateMatrix для создания матриц, затем измеряет время выполнения multiplyMatricesSequential и multiplyMatricesParallel с различными параметрами, выводит результаты. +3. matrix.worker.js +multiplyPartial(A, B, start, end): +- Воркеры выполняют умножение только для части матриц, определенной параметрами start и end, и возвращают частичные результаты через parentPort. + +## Запуск +``` +node benchmark.js +``` + +## Результат работы +> [!IMPORTANT] +> ![benchmark.png](./benchmark.png) +> +> В отчете отражены времена выполнения для каждого из подходов, что позволяет оценить, как число потоков влияет на скорость вычислений для матриц разного размера. + +Ссылка на видео: https://cloud.mail.ru/public/rEGy/HaBwrm7t8 diff --git a/bondarenko_max_lab_5/benchmark.js b/bondarenko_max_lab_5/benchmark.js new file mode 100644 index 0000000..b5968a4 --- /dev/null +++ b/bondarenko_max_lab_5/benchmark.js @@ -0,0 +1,29 @@ +const { multiplyMatricesSequential, multiplyMatricesParallel } = require('./matrix.operations'); + +function generateMatrix(size) { + return Array.from({ length: size }, () => Array.from({ length: size }, () => Math.floor(Math.random() * 100))); +} + +async function benchmark() { + const sizes = [100, 300, 500]; + const numThreads = [1, 2, 4, 8]; + + for (const size of sizes) { + const A = generateMatrix(size); + const B = generateMatrix(size); + + console.log(`\nMatrix size: ${size}x${size}`); + + console.time(`Sequential (${size}x${size})`); + multiplyMatricesSequential(A, B); + console.timeEnd(`Sequential (${size}x${size})`); + + for (const threads of numThreads) { + console.time(`Parallel (${size}x${size}, ${threads} threads)`); + await multiplyMatricesParallel(A, B, threads); + console.timeEnd(`Parallel (${size}x${size}, ${threads} threads)`); + } + } +} + +benchmark(); diff --git a/bondarenko_max_lab_5/benchmark.png b/bondarenko_max_lab_5/benchmark.png new file mode 100644 index 0000000..9653bf5 Binary files /dev/null and b/bondarenko_max_lab_5/benchmark.png differ diff --git a/bondarenko_max_lab_5/matrix.operations.js b/bondarenko_max_lab_5/matrix.operations.js new file mode 100644 index 0000000..879187d --- /dev/null +++ b/bondarenko_max_lab_5/matrix.operations.js @@ -0,0 +1,60 @@ +const { Worker } = require('worker_threads'); + +function multiplyMatricesSequential(A, B) { + const n = A.length; + const C = Array.from({ length: n }, () => Array(n).fill(0)); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + for (let k = 0; k < n; k++) { + C[i][j] += A[i][k] * B[k][j]; + } + } + } + return C; +} + +function multiplyMatricesParallel(A, B, numThreads) { + return new Promise((resolve, reject) => { + const n = A.length; + const step = Math.ceil(n / numThreads); + const workers = []; + const results = Array.from({ length: numThreads }, () => Array.from({ length: n }, () => Array(n).fill(0))); + + for (let i = 0; i < numThreads; i++) { + const start = i * step; + const end = Math.min(start + step, n); + workers.push( + new Promise((res, rej) => { + const worker = new Worker('./matrix.worker.js', { + workerData: { A, B, start, end } + }); + worker.on('message', result => { + results[i] = result; + res(); + }); + worker.on('error', rej); + worker.on('exit', code => { + if (code !== 0) rej(new Error(`Worker stopped with exit code ${code}`)); + }); + }) + ); + } + + Promise.all(workers) + .then(() => { + const C = Array.from({ length: n }, () => Array(n).fill(0)); + for (let i = 0; i < numThreads; i++) { + for (let j = 0; j < n; j++) { + for (let k = 0; k < n; k++) { + C[j][k] += results[i][j][k]; + } + } + } + resolve(C); + }) + .catch(reject); + }); +} + +module.exports = { multiplyMatricesSequential, multiplyMatricesParallel }; \ No newline at end of file diff --git a/bondarenko_max_lab_5/matrix.worker.js b/bondarenko_max_lab_5/matrix.worker.js new file mode 100644 index 0000000..00173d1 --- /dev/null +++ b/bondarenko_max_lab_5/matrix.worker.js @@ -0,0 +1,19 @@ +const { parentPort, workerData } = require('worker_threads'); + +function multiplyMatricesPart(A, B, start, end) { + const n = A.length; + const C = Array.from({ length: n }, () => Array(n).fill(0)); + + for (let i = start; i < end; ++i) { + for (let j = 0; j < n; ++j) { + for (let k = 0; k < n; ++k) { + C[i][j] += A[i][k] * B[k][j]; + } + } + } + return C; +} + +const { A, B, start, end } = workerData; +const result = multiplyMatricesPart(A, B, start, end); +parentPort.postMessage(result);