-
Notifications
You must be signed in to change notification settings - Fork 80
Дорофеев Иван. Технология SEQ-MPI. Интегрирование – метод Монте-Карло. Вариант 21. #65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
allnes
merged 13 commits into
learning-process:master
from
4elodoy-Molovek:dorofeev_i_monte_carlo_integration
Dec 10, 2025
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
c946be7
well i think it works
6b822c9
fixing clang-tidy
c92e4c4
fixing clang-tidy 2
3366e93
fixing clang-tidy 3
5d8a473
fixing clang-tidy 4
33daa89
report done
ad8e101
fixing coverage
4elodoy-Molovek bc0bd97
fixing coverage 2
4elodoy-Molovek a88ddcc
doing bcast and trying to do validation tests
4elodoy-Molovek e8908c4
fixing coverage 2
4elodoy-Molovek 9448c41
correcting comments
4elodoy-Molovek c971c57
corrercting comments 2
4elodoy-Molovek 5d9fe6b
fixing tests
4elodoy-Molovek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
25 changes: 25 additions & 0 deletions
25
tasks/dorofeev_i_monte_carlo_integration/common/include/common.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| #pragma once | ||
|
|
||
| #include <functional> | ||
| #include <string> | ||
| #include <tuple> | ||
| #include <vector> | ||
|
|
||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace dorofeev_i_monte_carlo_integration_processes { | ||
|
|
||
| struct InputData { | ||
| std::function<double(const std::vector<double> &)> func; // f(x) | ||
| std::vector<double> a; // lower bounds | ||
| std::vector<double> b; // upper bounds | ||
| int samples = 0; // number of samples | ||
| }; | ||
|
|
||
| using InType = InputData; | ||
| using OutType = double; | ||
|
|
||
| using TestType = std::tuple<int, std::string>; // for testing purposes | ||
| using BaseTask = ppc::task::Task<InType, OutType>; | ||
|
|
||
| } // namespace dorofeev_i_monte_carlo_integration_processes |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "student": { | ||
| "first_name": "Дорофеев", | ||
| "last_name": "Иван", | ||
| "middle_name": "Денисович", | ||
| "group_number": "3823Б1ФИ1", | ||
| "task_number": "1" | ||
| } | ||
| } |
22 changes: 22 additions & 0 deletions
22
tasks/dorofeev_i_monte_carlo_integration/mpi/include/ops_mpi.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| #pragma once | ||
|
|
||
| #include "dorofeev_i_monte_carlo_integration/common/include/common.hpp" | ||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace dorofeev_i_monte_carlo_integration_processes { | ||
|
|
||
| class DorofeevIMonteCarloIntegrationMPI : public BaseTask { | ||
| public: | ||
| static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { | ||
| return ppc::task::TypeOfTask::kMPI; | ||
| } | ||
| explicit DorofeevIMonteCarloIntegrationMPI(const InType &in); | ||
|
|
||
| private: | ||
| bool ValidationImpl() override; | ||
| bool PreProcessingImpl() override; | ||
| bool RunImpl() override; | ||
| bool PostProcessingImpl() override; | ||
| }; | ||
|
|
||
| } // namespace dorofeev_i_monte_carlo_integration_processes |
138 changes: 138 additions & 0 deletions
138
tasks/dorofeev_i_monte_carlo_integration/mpi/src/ops_mpi.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| #include "dorofeev_i_monte_carlo_integration/mpi/include/ops_mpi.hpp" | ||
|
|
||
| #include <mpi.h> | ||
|
|
||
| #include <algorithm> | ||
| #include <cstddef> | ||
| #include <random> | ||
| #include <ranges> | ||
| #include <utility> | ||
| #include <vector> | ||
|
|
||
| #include "dorofeev_i_monte_carlo_integration/common/include/common.hpp" | ||
|
|
||
| namespace dorofeev_i_monte_carlo_integration_processes { | ||
|
|
||
| DorofeevIMonteCarloIntegrationMPI::DorofeevIMonteCarloIntegrationMPI(const InType &in) { | ||
| SetTypeOfTask(GetStaticTypeOfTask()); | ||
| GetInput() = in; | ||
| GetOutput() = 0; | ||
| } | ||
|
|
||
| bool DorofeevIMonteCarloIntegrationMPI::ValidationImpl() { | ||
| int rank = 0; | ||
| MPI_Comm_rank(MPI_COMM_WORLD, &rank); | ||
|
|
||
| bool valid = true; | ||
|
|
||
| if (rank == 0) { | ||
| const auto &in = GetInput(); | ||
| valid = | ||
| in.func && !in.a.empty() && in.a.size() == in.b.size() && | ||
| std::ranges::all_of(std::views::iota(size_t{0}, in.a.size()), [&](size_t i) { return in.b[i] > in.a[i]; }) && | ||
| in.samples > 0; | ||
| } | ||
|
|
||
| MPI_Bcast(&valid, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD); | ||
| return valid; | ||
| } | ||
|
|
||
| bool DorofeevIMonteCarloIntegrationMPI::PreProcessingImpl() { | ||
| GetOutput() = 0.0; | ||
| return true; | ||
| } | ||
|
|
||
| bool DorofeevIMonteCarloIntegrationMPI::RunImpl() { | ||
| int rank = 0; | ||
| int size = 0; | ||
| MPI_Comm_rank(MPI_COMM_WORLD, &rank); | ||
| MPI_Comm_size(MPI_COMM_WORLD, &size); | ||
|
|
||
| // BROADCAST INPUT | ||
| InType in; | ||
|
|
||
| if (rank == 0) { | ||
| in = GetInput(); | ||
| } | ||
|
|
||
| // BROADCAST DIMS | ||
| int dims = static_cast<int>(rank == 0 ? in.a.size() : 0); | ||
| MPI_Bcast(&dims, 1, MPI_INT, 0, MPI_COMM_WORLD); | ||
|
|
||
| // resize on other ranks | ||
| if (rank != 0) { | ||
| in.a.resize(dims); | ||
| in.b.resize(dims); | ||
| } | ||
|
|
||
| // BROADCAST BOUNDS | ||
| MPI_Bcast(in.a.data(), dims, MPI_DOUBLE, 0, MPI_COMM_WORLD); | ||
| MPI_Bcast(in.b.data(), dims, MPI_DOUBLE, 0, MPI_COMM_WORLD); | ||
|
|
||
| // BROADCAST SAMPLES | ||
| MPI_Bcast(&in.samples, 1, MPI_INT, 0, MPI_COMM_WORLD); | ||
|
|
||
| // BROADCAST FUNC ID | ||
| int func_id = (rank == 0 ? 1 : 0); | ||
| MPI_Bcast(&func_id, 1, MPI_INT, 0, MPI_COMM_WORLD); | ||
|
|
||
| // restore the function | ||
| switch (func_id) { | ||
| case 1: | ||
| in.func = [](const std::vector<double> &x) { return x[0] * x[0]; }; | ||
| break; | ||
| default: | ||
| in.func = nullptr; | ||
| } | ||
|
|
||
| // CALCULATIONS | ||
| int n_total = in.samples; | ||
| int n_local = n_total / size; | ||
| if (rank == size - 1) { | ||
| n_local += n_total % size; | ||
| } | ||
|
4elodoy-Molovek marked this conversation as resolved.
|
||
|
|
||
| std::vector<std::uniform_real_distribution<double>> dist; | ||
| dist.reserve(dims); | ||
| for (int dim = 0; std::cmp_less(dim, dims); dim++) { | ||
| dist.emplace_back(in.a[dim], in.b[dim]); | ||
| } | ||
|
|
||
| std::mt19937 gen(rank + 777); | ||
| double local_sum = 0.0; | ||
|
|
||
| std::vector<double> x; | ||
| x.assign(static_cast<size_t>(dims), 0.0); | ||
|
|
||
| for (int i = 0; i < n_local; ++i) { | ||
| for (int dim = 0; std::cmp_less(dim, dims); dim++) { | ||
| x[static_cast<size_t>(dim)] = dist[dim](gen); | ||
| } | ||
| local_sum += in.func(x); | ||
| } | ||
|
|
||
| // REDUCE | ||
| double global_sum = 0.0; | ||
| MPI_Reduce(&local_sum, &global_sum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); | ||
|
|
||
| // RESULT | ||
| double result = 0.0; | ||
| if (rank == 0) { | ||
| double volume = 1.0; | ||
| for (int dim = 0; std::cmp_less(dim, dims); dim++) { | ||
| volume *= (in.b[dim] - in.a[dim]); | ||
| } | ||
| result = (global_sum / n_total) * volume; | ||
| } | ||
|
|
||
| MPI_Bcast(&result, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); | ||
|
|
||
| GetOutput() = result; | ||
| return true; | ||
| } | ||
|
|
||
| bool DorofeevIMonteCarloIntegrationMPI::PostProcessingImpl() { | ||
| return true; | ||
| } | ||
|
|
||
| } // namespace dorofeev_i_monte_carlo_integration_processes | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| # Интегрирование – метод Монте-Карло | ||
|
|
||
| **Student:** Дорофеев Иван Денисович, group 3823Б1ФИ1 | ||
| **Technology:** SEQ | MPI | ||
| **Variant:** 21 | ||
|
|
||
| --- | ||
|
|
||
| ## 1. Introduction | ||
|
|
||
| Метод Монте-Карло — один из универсальных способов численного интегрирования, позволяющий эффективно оценивать интегралы любой размерности. Однако точность метода и время работы напрямую зависят от количества случайных выборок (samples). Увеличение количества выборок повышает точность, но также увеличивает время выполнения, что делает задачу подходящей для распараллеливания. | ||
|
|
||
| Ожидается, что MPI-версия позволит уменьшить время выполнения за счёт распределения выборок между процессами. | ||
|
|
||
| --- | ||
|
|
||
| ## 2. Problem statement | ||
|
|
||
| Требуется вычислить значение определённого интеграла методом Монте-Карло. | ||
|
|
||
| ### Входные данные: | ||
|
|
||
| - Границы интегрирования: | ||
| $a = 0,\quad b = 1$ | ||
|
|
||
| - Количество выборок: 190000 | ||
|
|
||
| - Функция: | ||
| $f(x) = x^2$ | ||
|
|
||
| ### Выходные данные: | ||
|
|
||
| - Одно действительное число — приближённое значение интеграла. | ||
|
|
||
| --- | ||
|
|
||
| ## 3. Baseline Algorithm (Sequential) | ||
|
|
||
| 1. Сгенерировать N равномерных случайных точек из интервала $[a, b]$. | ||
|
|
||
| 2. Вычислить значение функции в каждой точке. | ||
|
|
||
| 3. Найти среднее всех вычисленных значений. | ||
|
|
||
| 4. Умножить среднее на длину интервала $(b-a)$. | ||
|
|
||
| Последовательная реализация проста, но требует выполнения всех N вычислений в одном процессе. | ||
|
|
||
| --- | ||
|
|
||
| ## 4. Parallelization Scheme (MPI) | ||
|
|
||
| Для распараллеливания используется идея независимости выборок: | ||
| каждый процесс может самостоятельно выполнить часть выборок и затем отправить свой частичный результат. | ||
|
|
||
| ### Схема: | ||
|
|
||
| 1. Корневой процесс рассылает параметры задачи всем участникам. | ||
|
|
||
| 2. Каждый процесс: | ||
|
|
||
| - выполняет часть выборок: | ||
| $N_p = \frac{N}{P} $ | ||
|
|
||
| - рассчитывает среднее значение функции на своём подмножестве. | ||
|
|
||
| 3. Результаты всех процессов объединяются с помощью **MPI_Reduce**. | ||
|
|
||
| 4. Корневой процесс вычисляет итоговый интеграл. | ||
|
|
||
| Поскольку метод Монте-Карло "естественно" распараллеливается, эффективность MPI в идеальных условиях может быть высокой. | ||
|
|
||
| --- | ||
|
|
||
| ## 5. Experimental Setup | ||
|
|
||
| - Hardware/OS: | ||
| - CPU: 13th Gen Intel i5-13420H (12) @ 4.6GHz, 8 ядер | ||
| - RAM: 16GB RAM | ||
| - OS: Ubuntu 25.10 x86_64 | ||
| - Среда выполнения: Docker (Ubuntu trixie/sid (noble) x86_64) | ||
| - Toolchain: compiler, version, build type (Release/RelWithDebInfo) | ||
| - CMake 3.28.3 | ||
| - g++ 13.3.0 | ||
| - OpenMPI | ||
| - Сборка: Release | ||
| - Data: | ||
| - Количество выборок: 190000 | ||
| - Функция: $f(x)=x^2$ | ||
| - Тесты производительности запускались для **SEQ**, **MPI: 2**, **MPI: 4** процессов. | ||
|
|
||
| --- | ||
|
|
||
| ## 6. Results and Discussion | ||
|
|
||
| ### 6.1 Correctness | ||
|
|
||
| Корректность проверена тестами GoogleTest. | ||
| Точное значение интеграла: | ||
|
|
||
| $\int_0^1 x^2 dx = \frac{1}{3} \approx 0.333333 $ | ||
|
|
||
|
|
||
| Все варианты укладываются в допуск ±0.05. | ||
|
|
||
| --- | ||
|
|
||
| ## 6.2 Performance | ||
|
|
||
| | Mode | Processes | Time (s) | Speedup | Efficiency | | ||
| | ------- | --------- | ------------ | -------- | ---------- | | ||
| | **seq** | 1 | **0.002277** | **1.00** | — | | ||
| | **mpi** | 2 | **0.001751** | **1.30** | **65%** | | ||
| | **mpi** | 4 | **0.001137** | **2.00** | **50%** | | ||
|
|
||
| --- | ||
|
|
||
| ## 7. Discussion | ||
|
|
||
| Результаты экспериментов показывают, что MPI-версия действительно работает быстрее последовательной SEQ-реализации при одинаковом количестве выборок. | ||
|
|
||
| Для 2 процессов ускорение составляет **1.30×** при эффективности **65%**. | ||
| Для 4 процессов ускорение достигает **2.00×**, что соответствует эффективности **50%**. | ||
|
|
||
| Эффективность снижается с ростом числа процессов, это ожидаемое поведение для MPI, так как накладные расходы растут, а объём работы, приходящийся на каждый процесс, уменьшается. | ||
|
|
||
| Основные источники потерь производительности: | ||
|
|
||
| - необходимость синхронизации между процессами, | ||
|
|
||
| - выполнение коллективных операций (например, **MPI_Allreduce**), | ||
|
|
||
| - накладные расходы MPI, усиливающиеся при запуске внутри Docker-контейнера, | ||
|
|
||
| - относительно малый объём вычислений на один процесс при 4-процессном запуске. | ||
|
|
||
| Тем не менее ускорение остаётся значительным — даже с учётом накладных расходов распараллеливание уменьшает общее время расчёта примерно вдвое. | ||
|
|
||
| --- | ||
|
|
||
| ## 8. Conclusions | ||
|
|
||
| Метод Монте-Карло хорошо поддаётся параллелизации, и MPI-версия показывает ощутимое ускорение. | ||
|
|
||
| Хотя эффективность не достигает 100% из-за накладных расходов, ускорение в 2 раза при использовании 4 процессов подтверждает преимущества распараллеливания. | ||
|
|
||
| MPI-подход особенно полезен при значительно больших объёмах выборок, где накладные расходы становятся менее заметными. | ||
|
|
||
| --- | ||
|
|
||
| ## 9. References | ||
|
|
||
| 1. "Параллельное программирование для кластерных систем" ИИТММ, ННГУ им. Лобачевского | ||
| 2. [Open MPI Documentation](https://www.open-mpi.org/doc/) | ||
| 3. [MPI Reference - Message Passing Interface | Microsoft Learn](https://learn.microsoft.com/en-us/message-passing-interface/mpi-reference) | ||
| 4. [MPI: A Message-Passing Interface Standard](https://www.mpi-forum.org/docs/mpi-5.0/mpi50-report.pdf) | ||
|
|
||
|
|
22 changes: 22 additions & 0 deletions
22
tasks/dorofeev_i_monte_carlo_integration/seq/include/ops_seq.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| #pragma once | ||
|
|
||
| #include "dorofeev_i_monte_carlo_integration/common/include/common.hpp" | ||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace dorofeev_i_monte_carlo_integration_processes { | ||
|
|
||
| class DorofeevIMonteCarloIntegrationSEQ : public BaseTask { | ||
| public: | ||
| static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { | ||
| return ppc::task::TypeOfTask::kSEQ; | ||
| } | ||
| explicit DorofeevIMonteCarloIntegrationSEQ(const InType &in); | ||
|
|
||
| private: | ||
| bool ValidationImpl() override; | ||
| bool PreProcessingImpl() override; | ||
| bool RunImpl() override; | ||
| bool PostProcessingImpl() override; | ||
| }; | ||
|
|
||
| } // namespace dorofeev_i_monte_carlo_integration_processes |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.