generated from learning-process/parallel_programming_course
-
Notifications
You must be signed in to change notification settings - Fork 78
Шеленкова Мария. Технология SEQ-MPI. Скалярное произведение векторов. Вариант 9. #100
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
Open
mariashelenkova
wants to merge
8
commits into
learning-process:master
Choose a base branch
from
mariashelenkova:mariashelenkova_skalar_vector
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+414
−0
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
3efe440
Shelenkova
mariashelenkova 8088b6b
corrected
mariashelenkova d12d23d
fix
mariashelenkova 537e287
fix2
mariashelenkova 3368834
fix3
mariashelenkova dcabf4d
fix4
mariashelenkova 5789808
fix5
mariashelenkova 0c8f9e0
FIX
mariashelenkova 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
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,18 @@ | ||
| #pragma once | ||
|
|
||
| #include <vector> | ||
|
|
||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace vector_scalar_product { | ||
|
|
||
| struct DotProductInput { | ||
| std::vector<double> lhs; | ||
| std::vector<double> rhs; | ||
| }; | ||
|
|
||
| using InType = DotProductInput; | ||
| using OutType = double; | ||
| using BaseTask = ppc::task::Task<InType, OutType>; | ||
|
|
||
| } // namespace vector_scalar_product |
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,3 @@ | ||
| 8,1.2 -3.4 5.1 0.0 2.8 -1.7 4.3 9.1,0.5 3.6 -2.1 4.8 -1.2 0.0 7.3 2.2 | ||
| 16,2.4 -1.1 0.0 3.9 5.6 -2.7 8.8 -4.4 6.6 -3.3 1.1 4.2 -5.8 7.9 -0.6 2.0,-1.5 2.7 3.3 -4.1 6.0 -7.2 1.5 2.8 -0.9 5.5 -3.6 4.4 2.2 -1.8 0.0 3.1 | ||
| 24,0.25 0.5 0.75 1.0 1.25 1.5 1.75 2.0 2.25 2.5 2.75 3.0 3.25 3.5 3.75 4.0 4.25 4.5 4.75 5.0 5.25 5.5 5.75 6.0,6.0 5.75 5.5 5.25 5.0 4.75 4.5 4.25 4.0 3.75 3.5 3.25 3.0 2.75 2.5 2.25 2.0 1.75 1.5 1.25 1.0 0.75 0.5 0.25 |
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": "9" | ||
| } | ||
| } |
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,32 @@ | ||
| #pragma once | ||
|
|
||
| #include <vector> | ||
|
|
||
| #include "task/include/task.hpp" | ||
| #include "vector_scalar_product/common/include/common.hpp" | ||
|
|
||
| namespace vector_scalar_product { | ||
|
|
||
| class VectorScalarProductMpi : public BaseTask { | ||
| public: | ||
| static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { | ||
| return ppc::task::TypeOfTask::kMPI; | ||
| } | ||
|
|
||
| explicit VectorScalarProductMpi(const InType &in); | ||
|
|
||
| private: | ||
| bool ValidationImpl() override; | ||
| bool PreProcessingImpl() override; | ||
| bool RunImpl() override; | ||
| bool PostProcessingImpl() override; | ||
|
|
||
| int rank_ = 0; | ||
| int world_size_ = 1; | ||
| std::vector<double> local_lhs_; | ||
| std::vector<double> local_rhs_; | ||
| double local_sum_ = 0.0; | ||
| double result_ = 0.0; | ||
| }; | ||
|
|
||
| } // namespace vector_scalar_product |
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,92 @@ | ||
| #include "vector_scalar_product/mpi/include/ops_mpi.hpp" | ||
|
|
||
| #include <mpi.h> | ||
|
|
||
| #include <cstddef> | ||
| #include <numeric> | ||
| #include <vector> | ||
|
|
||
| #include "vector_scalar_product/common/include/common.hpp" | ||
|
|
||
| namespace vector_scalar_product { | ||
| namespace { | ||
| std::vector<int> BuildCounts(int total, int parts) { | ||
| std::vector<int> counts(parts, 0); | ||
| const int base = total / parts; | ||
| int remainder = total % parts; | ||
| for (int i = 0; i < parts; ++i) { | ||
| counts[i] = base + (remainder > 0 ? 1 : 0); | ||
| if (remainder > 0) { | ||
| --remainder; | ||
| } | ||
| } | ||
| return counts; | ||
| } | ||
|
|
||
| std::vector<int> BuildDisplacements(const std::vector<int> &counts) { | ||
| std::vector<int> displs(counts.size(), 0); | ||
| for (std::size_t i = 1; i < counts.size(); ++i) { | ||
| displs[i] = displs[i - 1] + counts[i - 1]; | ||
| } | ||
| return displs; | ||
| } | ||
| } // namespace | ||
|
|
||
| VectorScalarProductMpi::VectorScalarProductMpi(const InType &in) { | ||
| SetTypeOfTask(GetStaticTypeOfTask()); | ||
| GetInput() = in; | ||
| GetOutput() = 0.0; | ||
| } | ||
|
|
||
| bool VectorScalarProductMpi::ValidationImpl() { | ||
| const auto &lhs = GetInput().lhs; | ||
| const auto &rhs = GetInput().rhs; | ||
| return !lhs.empty() && lhs.size() == rhs.size(); | ||
| } | ||
|
|
||
| bool VectorScalarProductMpi::PreProcessingImpl() { | ||
| MPI_Comm_rank(MPI_COMM_WORLD, &rank_); | ||
| MPI_Comm_size(MPI_COMM_WORLD, &world_size_); | ||
|
|
||
| const auto &lhs = GetInput().lhs; | ||
| const auto &rhs = GetInput().rhs; | ||
| int global_size = 0; | ||
| if (rank_ == 0) { | ||
| global_size = static_cast<int>(lhs.size()); | ||
| } | ||
| MPI_Bcast(&global_size, 1, MPI_INT, 0, MPI_COMM_WORLD); | ||
|
|
||
| // Prepare scattering meta information | ||
| auto counts = BuildCounts(global_size, world_size_); | ||
| auto displs = BuildDisplacements(counts); | ||
| const int local_count = counts[rank_]; | ||
|
|
||
| local_lhs_.assign(static_cast<std::size_t>(local_count), 0.0); | ||
| local_rhs_.assign(static_cast<std::size_t>(local_count), 0.0); | ||
|
|
||
| const double *lhs_ptr = rank_ == 0 ? lhs.data() : nullptr; | ||
| const double *rhs_ptr = rank_ == 0 ? rhs.data() : nullptr; | ||
|
|
||
| MPI_Scatterv(lhs_ptr, counts.data(), displs.data(), MPI_DOUBLE, local_lhs_.data(), local_count, MPI_DOUBLE, 0, | ||
| MPI_COMM_WORLD); | ||
| MPI_Scatterv(rhs_ptr, counts.data(), displs.data(), MPI_DOUBLE, local_rhs_.data(), local_count, MPI_DOUBLE, 0, | ||
| MPI_COMM_WORLD); | ||
|
|
||
| local_sum_ = 0.0; | ||
| result_ = 0.0; | ||
| return true; | ||
| } | ||
|
|
||
| bool VectorScalarProductMpi::RunImpl() { | ||
| local_sum_ = std::inner_product(local_lhs_.begin(), local_lhs_.end(), local_rhs_.begin(), 0.0); | ||
|
|
||
| return MPI_Reduce(&local_sum_, &result_, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD) == MPI_SUCCESS; | ||
| } | ||
|
|
||
| bool VectorScalarProductMpi::PostProcessingImpl() { | ||
| MPI_Bcast(&result_, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); | ||
| GetOutput() = result_; | ||
| return true; | ||
| } | ||
|
|
||
| } // namespace vector_scalar_product |
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,52 @@ | ||
| # Отчет по лабораторной работе №1 | ||
| ## "Скалярное произведение векторов" | ||
|
|
||
| **Студент:** Шеленкова Мария Сергеевна | ||
| **Группа:** 3823Б1ФИ1 | ||
| **Вариант:** 9 | ||
|
|
||
| ### 1. Введение | ||
| **Мотивация.** Скалярное произведение лежит в основе множества алгоритмов линейной алгебры и анализа данных, поэтому важно исследовать его последовательную и параллельную реализации. | ||
| **Проблематика.** Операция элементарна и содержит мало вычислений на одну итерацию. Коммуникационные накладные расходы могут превысить выигрыш от распараллеливания. | ||
| **Ожидаемый результат.** Предполагалось, что параллельная версия окажется эффективной только для очень длинных векторов; на малых размерах преимущество сохранит последовательный алгоритм. | ||
|
|
||
| ### 2. Постановка задачи | ||
| **Задано:** два вещественных вектора одинаковой длины. | ||
| **Требуется:** вычислить их скалярное произведение. | ||
| **Входные данные:** массивы `double a[i]`, `double b[i]`, `size_t n`. | ||
| **Выходные данные:** значение `double result`. | ||
|
|
||
| ### 3. Последовательный алгоритм | ||
| 1. Проверяются корректность входных данных и равенство размеров векторов. | ||
| 2. Используется стандартная функция `std::inner_product`, последовательно перемножающая пары элементов и суммирующая результат. | ||
| 3. Алгоритм имеет линейную сложность `O(n)` и использует константный объём дополнительной памяти. | ||
|
|
||
| ### 4. Схема распараллеливания | ||
| **Декомпозиция данных.** Индексный диапазон разделяется на блоки по числу процессов. Первые `n % P` процессов получают на один элемент больше. | ||
| **Коммуникация.** Корневой процесс рассылает длину векторов и параметры распределения с помощью `MPI_Bcast`. После локальных вычислений частичные суммы сводятся к корню через `MPI_Reduce` с операцией `MPI_SUM`; при необходимости результат снова транслируется `MPI_Bcast`. Дополнительных синхронизаций не требуется. | ||
|
|
||
| ### 5. Экспериментальная установка | ||
| * Процессор: 13th Gen Intel(R) Core(TM) i9-13980HX (24 физических ядра, 32 логических потока). | ||
| * Оперативная память: 32 GB. | ||
| * Операционная система: Microsoft Windows 11 Pro. | ||
| * Компилятор: MSVC 19.40, конфигурация Release x64. | ||
| * MPI-библиотека: Microsoft MPI 10.1.12498.52. | ||
|
|
||
| ### 6. Результаты и обсуждение | ||
| #### 6.1. Корректность | ||
| Проверка выполнена командой `ppc_func_tests.exe --gtest_filter=*vector_scalar_product*`. Все тесты завершились успешно; значения параллельной версии совпадают с последовательным эталоном. | ||
|
|
||
| #### 6.2. Производительность | ||
| Измерения проводились с помощью `ppc_perf_tests.exe --gtest_filter=*vector_scalar_product*`, размер тестового входа — 20 млн элементов. Последовательный вариант запускался на одном процессе, параллельный — на восьми (`mpiexec -n 8`). | ||
|
|
||
| | Реализация | Процессов | Режим теста | Время, сек | | ||
| |-----------:|----------:|-------------|-----------:| | ||
| | seq | 1 | pipeline | 0.012362 | | ||
| | seq | 1 | task_only | 0.012612 | | ||
| | mpi | 8 | pipeline | 0.063408 | | ||
| | mpi | 8 | task_only | 0.012235 | | ||
|
|
||
| При чистом `task_only` MPI-версия достигла близкой к последовательной скорости, но конвейерная цепочка осталась медленнее из-за стоимости распределения и сбора данных. Даже при увеличенном размере вектора ускорение не появляется. | ||
|
|
||
| ### 7. Выводы | ||
| Последовательный алгоритм остаётся предпочтительным для небольших векторов, где коммуникационные затраты доминируют. Реализация MPI корректна и готова к масштабированию на большие объёмы данных, при которых вычислительная нагрузка превысит стоимость обменов. | ||
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 "task/include/task.hpp" | ||
| #include "vector_scalar_product/common/include/common.hpp" | ||
|
|
||
| namespace vector_scalar_product { | ||
|
|
||
| class VectorScalarProductSeq : public BaseTask { | ||
| public: | ||
| static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { | ||
| return ppc::task::TypeOfTask::kSEQ; | ||
| } | ||
|
|
||
| explicit VectorScalarProductSeq(const InType &in); | ||
|
|
||
| private: | ||
| bool ValidationImpl() override; | ||
| bool PreProcessingImpl() override; | ||
| bool RunImpl() override; | ||
| bool PostProcessingImpl() override; | ||
|
|
||
| double partial_sum_ = 0.0; | ||
| }; | ||
|
|
||
| } // namespace vector_scalar_product |
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,38 @@ | ||
| #include "vector_scalar_product/seq/include/ops_seq.hpp" | ||
|
|
||
| #include <numeric> | ||
|
|
||
| #include "vector_scalar_product/common/include/common.hpp" | ||
|
|
||
| namespace vector_scalar_product { | ||
|
|
||
| VectorScalarProductSeq::VectorScalarProductSeq(const InType &in) { | ||
| SetTypeOfTask(GetStaticTypeOfTask()); | ||
| GetInput() = in; | ||
| GetOutput() = 0.0; | ||
| } | ||
|
|
||
| bool VectorScalarProductSeq::ValidationImpl() { | ||
| const auto &lhs = GetInput().lhs; | ||
| const auto &rhs = GetInput().rhs; | ||
| return !lhs.empty() && lhs.size() == rhs.size(); | ||
| } | ||
|
|
||
| bool VectorScalarProductSeq::PreProcessingImpl() { | ||
| partial_sum_ = 0.0; | ||
| return true; | ||
| } | ||
|
|
||
| bool VectorScalarProductSeq::RunImpl() { | ||
| const auto &lhs = GetInput().lhs; | ||
| const auto &rhs = GetInput().rhs; | ||
| partial_sum_ = std::inner_product(lhs.begin(), lhs.end(), rhs.begin(), 0.0); | ||
| return true; | ||
| } | ||
|
|
||
| bool VectorScalarProductSeq::PostProcessingImpl() { | ||
| GetOutput() = partial_sum_; | ||
| return true; | ||
| } | ||
|
|
||
| } // namespace vector_scalar_product |
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,7 @@ | ||
| { | ||
| "tasks_type": "processes", | ||
| "tasks": { | ||
| "mpi": "enabled", | ||
| "seq": "enabled" | ||
| } | ||
| } |
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,80 @@ | ||
| #include <gtest/gtest.h> | ||
|
|
||
| #include <array> | ||
| #include <cmath> | ||
| #include <cstddef> | ||
| #include <numbers> | ||
| #include <string> | ||
| #include <tuple> | ||
| #include <vector> | ||
|
|
||
| #include "util/include/func_test_util.hpp" | ||
| #include "util/include/util.hpp" | ||
| #include "vector_scalar_product/common/include/common.hpp" | ||
| #include "vector_scalar_product/mpi/include/ops_mpi.hpp" | ||
| #include "vector_scalar_product/seq/include/ops_seq.hpp" | ||
|
|
||
| namespace vector_scalar_product { | ||
|
|
||
| struct DotProductCase { | ||
| std::vector<double> lhs; | ||
| std::vector<double> rhs; | ||
| double expected = 0.0; | ||
| }; | ||
|
|
||
| using TestType = DotProductCase; | ||
|
|
||
| class VectorScalarProductFuncTests : public ppc::util::BaseRunFuncTests<InType, OutType, TestType> { | ||
| public: | ||
| static std::string PrintTestParam(const TestType ¶m) { | ||
| const auto size_tag = std::to_string(param.lhs.size()); | ||
| const auto value_tag = std::to_string(static_cast<int>(param.expected)); | ||
| return size_tag + "_" + value_tag; | ||
| } | ||
|
|
||
| protected: | ||
| void SetUp() override { | ||
| const auto ¶m = std::get<static_cast<std::size_t>(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); | ||
| input_.lhs = param.lhs; | ||
| input_.rhs = param.rhs; | ||
| expected_ = param.expected; | ||
| } | ||
|
|
||
| InType GetTestInputData() final { | ||
| return input_; | ||
| } | ||
|
|
||
| bool CheckTestOutputData(OutType &output_data) final { | ||
| return std::fabs(output_data - expected_) < 1e-9; | ||
| } | ||
|
|
||
| private: | ||
| InType input_{}; | ||
| double expected_ = 0.0; | ||
| }; | ||
|
|
||
| namespace { | ||
|
|
||
| constexpr double kPi = std::numbers::pi; | ||
|
|
||
| const std::array<TestType, 3> kTestParams = {TestType{{1.0, 2.0, 3.0}, {4.0, -5.0, 6.0}, 12.0}, | ||
| TestType{{0.5, 1.5, -2.0, 4.0}, {2.0, 1.0, -1.0, 0.0}, 4.5}, | ||
| TestType{{kPi, 0.0, -kPi}, {1.0, 2.0, -1.0}, 2.0 * kPi}}; | ||
|
|
||
| const auto kTaskList = std::tuple_cat( | ||
| ppc::util::AddFuncTask<VectorScalarProductSeq, InType>(kTestParams, PPC_SETTINGS_vector_scalar_product), | ||
| ppc::util::AddFuncTask<VectorScalarProductMpi, InType>(kTestParams, PPC_SETTINGS_vector_scalar_product)); | ||
|
|
||
| const auto kGTestValues = ppc::util::ExpandToValues(kTaskList); | ||
|
|
||
| // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables,modernize-type-traits) | ||
| INSTANTIATE_TEST_SUITE_P(DotProduct, VectorScalarProductFuncTests, kGTestValues, | ||
| VectorScalarProductFuncTests::PrintFuncTestName<VectorScalarProductFuncTests>); | ||
|
|
||
| TEST_P(VectorScalarProductFuncTests, Runs) { | ||
| ExecuteTest(GetParam()); | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| } // namespace vector_scalar_product |
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3823Б1ФИ1 or 2 ? Data in
tasks/vector_scalar_product/info.jsonandtasks/vector_scalar_product/report.mdmismatch. Please, fix