From 25f8ce44eb60c6b523de257c21372ab978a51acd Mon Sep 17 00:00:00 2001 From: maxnes3 Date: Fri, 13 Dec 2024 23:51:05 +0400 Subject: [PATCH] bondarenko_max_lab_5_is_ready --- bondarenko_max_lab_5/README.md | 43 ++++++++++++++++ bondarenko_max_lab_5/benchmark.js | 29 +++++++++++ bondarenko_max_lab_5/benchmark.png | Bin 0 -> 53347 bytes bondarenko_max_lab_5/matrix.operations.js | 60 ++++++++++++++++++++++ bondarenko_max_lab_5/matrix.worker.js | 19 +++++++ 5 files changed, 151 insertions(+) create mode 100644 bondarenko_max_lab_5/README.md create mode 100644 bondarenko_max_lab_5/benchmark.js create mode 100644 bondarenko_max_lab_5/benchmark.png create mode 100644 bondarenko_max_lab_5/matrix.operations.js create mode 100644 bondarenko_max_lab_5/matrix.worker.js diff --git a/bondarenko_max_lab_5/README.md b/bondarenko_max_lab_5/README.md new file mode 100644 index 0000000..f530c69 --- /dev/null +++ b/bondarenko_max_lab_5/README.md @@ -0,0 +1,43 @@ +# Лабораторная работа 1 - Знакомство с Docker и Docker Compose +### ПИбд-42 || Бондаренко Максим + +# Описание работы + +## Цель +> [!NOTE] +> Изучение современных технологий контейнеризации. + +## Результат работы +> [!NOTE] +> Кратко: реализовать умножение двух больших квадратных матриц. +> +> Подробно: в лабораторной работе требуется сделать два алгоритма: обычный и параллельный (задание со * - реализовать это в рамках одного алгоритма). В параллельном алгоритме предусмотреть ручное задание количества потоков (число потоков = 1 как раз и реализует задание со *), каждый из которых будет выполнять умножение элементов матрицы в рамках своей зоны ответственности. + +## Краткое описание модулей и их работа +1. matrixOperations.js +multiplyMatricesSequential(A, B): +- Перебирает элементы матриц и вычисляет их произведение, заполняя результирующую матрицу. +multiplyMatricesParallel(A, B, numThreads): +- Делит работу между потоками, каждый из которых умножает часть матриц. Запускает воркеры и собирает их результаты. + +2. benchmark.js +generateMatrix(size): +- Создает матрицу с случайными значениями заданного размера. +benchmark(): +- Вызывает generateMatrix для создания матриц, затем измеряет время выполнения multiplyMatricesSequential и multiplyMatricesParallel с различными параметрами, выводит результаты. +3. matrixWorker.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 0000000000000000000000000000000000000000..9653bf5d0d23abc19df02cdaa43e2599c40b3ee6 GIT binary patch literal 53347 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 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);