Skip to content

Commit b2fbbe1

Browse files
mollycooddlemollycooddle
andauthored
Тельнов Анатолий. Технология SEQ-MPI. Алгоритм глобального поиска (Стронгина) для одномерных задач оптимизации. Распараллеливание по характеристикам. Вариант 11 (#148)
## Описание - **Задача**: Алгоритм глобального поиска (Стронгина) для одномерных задач оптимизации. Распараллеливание по характеристикам. - **Вариант**: 11 - **Технология**: SEQ-MPI - **Описание**: В работе реализован алгоритм глобальной оптимизации одномерной функции на отрезке с использованием метода Стронгина. Реализованы последовательная и параллельная (MPI) версии алгоритма. Параллелизация выполнена за счёт распределения вычисления характеристик интервалов между процессами с последующей синхронизацией через `MPI_Allreduce` и `MPI_Bcast`. В отчёте приведены описание алгоритма, схема распараллеливания, псевдокод, результаты проверки корректности и анализ производительности. --- ## Чек-лист - [x] **Статус CI**: Все CI-задачи (сборка, тесты, генерация отчёта) успешно проходят на моей ветке в моем форке - [x] **Директория и именование задачи**: Я создал директорию с именем `<фамилия>_<первая_буква_имени>_<короткое_название_задачи>` - [x] **Полное описание задачи**: Я предоставил полное описание задачи в теле pull request - [x] **clang-format**: Мои изменения успешно проходят `clang-format` локально в моем форке (нет ошибок форматирования) - [x] **clang-tidy**: Мои изменения успешно проходят `clang-tidy` локально в моем форке (нет предупреждений/ошибок) - [x] **Функциональные тесты**: Все функциональные тесты успешно проходят локально на моей машине - [x] **Тесты производительности**: Все тесты производительности успешно проходят локально на моей машине - [x] **Ветка**: Я работаю в ветке, названной точно так же, как директория моей задачи (например, `nesterov_a_vector_sum`), а не в `master` - [x] **Правдивое содержание**: Я подтверждаю, что все сведения, указанные в этом pull request, являются точными и достоверными --------- Co-authored-by: mollycooddle <toolya.telnoff@yandex.ru>
1 parent d4d8341 commit b2fbbe1

11 files changed

Lines changed: 669 additions & 0 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <tuple>
5+
6+
#include "task/include/task.hpp"
7+
8+
namespace telnov_strongin_algorithm {
9+
10+
struct StronginInput {
11+
double a;
12+
double b;
13+
double eps;
14+
};
15+
16+
using InType = StronginInput;
17+
using OutType = double;
18+
using TestType = std::tuple<int, std::string>;
19+
using BaseTask = ppc::task::Task<InType, OutType>;
20+
21+
} // namespace telnov_strongin_algorithm
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"student": {
3+
"first_name": "Анатолий",
4+
"last_name": "Тельнов",
5+
"middle_name": "Викторович",
6+
"group_number": "3823Б1ФИ2",
7+
"task_number": "11"
8+
}
9+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include "task/include/task.hpp"
4+
#include "telnov_strongin_algorithm/common/include/common.hpp"
5+
6+
namespace telnov_strongin_algorithm {
7+
8+
class TelnovStronginAlgorithmMPI : public BaseTask {
9+
public:
10+
static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() {
11+
return ppc::task::TypeOfTask::kMPI;
12+
}
13+
explicit TelnovStronginAlgorithmMPI(const InType &in);
14+
15+
private:
16+
bool ValidationImpl() override;
17+
bool PreProcessingImpl() override;
18+
bool RunImpl() override;
19+
bool PostProcessingImpl() override;
20+
};
21+
22+
} // namespace telnov_strongin_algorithm
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#include "telnov_strongin_algorithm/mpi/include/ops_mpi.hpp"
2+
3+
#include <mpi.h>
4+
5+
#include <algorithm>
6+
#include <cmath>
7+
#include <cstddef>
8+
#include <vector>
9+
10+
#include "telnov_strongin_algorithm/common/include/common.hpp"
11+
12+
namespace telnov_strongin_algorithm {
13+
14+
struct MaxData {
15+
double value{};
16+
int index{};
17+
};
18+
19+
TelnovStronginAlgorithmMPI::TelnovStronginAlgorithmMPI(const InType &in) {
20+
SetTypeOfTask(GetStaticTypeOfTask());
21+
GetInput() = in;
22+
GetOutput() = 0;
23+
}
24+
25+
bool TelnovStronginAlgorithmMPI::ValidationImpl() {
26+
const auto &in = GetInput();
27+
return (in.eps > 0.0) && (in.b > in.a);
28+
}
29+
30+
bool TelnovStronginAlgorithmMPI::PreProcessingImpl() {
31+
return true;
32+
}
33+
34+
bool TelnovStronginAlgorithmMPI::RunImpl() {
35+
int rank = 0;
36+
int size = 1;
37+
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
38+
MPI_Comm_size(MPI_COMM_WORLD, &size);
39+
40+
const auto &in = GetInput();
41+
const double eps = in.eps;
42+
43+
auto f = [](double x) { return ((x - 1.0) * (x - 1.0)) + 1.0; };
44+
45+
std::vector<double> x_vals{in.a, in.b};
46+
std::vector<double> f_vals{f(in.a), f(in.b)};
47+
48+
const double r = 2.0;
49+
const int k_max_iters = 100;
50+
int iter = 0;
51+
52+
while ((x_vals.back() - x_vals.front()) > eps && iter < k_max_iters) {
53+
++iter;
54+
55+
double m = 0.0;
56+
for (std::size_t i = 1; i < x_vals.size(); ++i) {
57+
const double dx = x_vals[i] - x_vals[i - 1];
58+
const double df = std::abs(f_vals[i] - f_vals[i - 1]);
59+
m = std::max(m, df / dx);
60+
}
61+
m = std::max(m, 1.0);
62+
63+
MaxData local_data;
64+
local_data.value = -1e9;
65+
local_data.index = 1;
66+
67+
for (std::size_t i = static_cast<std::size_t>(rank) + 1; i < x_vals.size(); i += static_cast<std::size_t>(size)) {
68+
const double dx = x_vals[i] - x_vals[i - 1];
69+
const double df = f_vals[i] - f_vals[i - 1];
70+
71+
const double r_val = (r * dx) + ((df * df) / (r * dx)) - (2.0 * (f_vals[i] + f_vals[i - 1]));
72+
73+
if (r_val > local_data.value) {
74+
local_data.value = r_val;
75+
local_data.index = static_cast<int>(i);
76+
}
77+
}
78+
79+
MaxData global_data{};
80+
MPI_Allreduce(&local_data, &global_data, 1, MPI_DOUBLE_INT, MPI_MAXLOC, MPI_COMM_WORLD);
81+
82+
if (rank != 0) {
83+
int n = 0;
84+
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
85+
x_vals.resize(static_cast<std::size_t>(n));
86+
f_vals.resize(static_cast<std::size_t>(n));
87+
MPI_Bcast(x_vals.data(), n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
88+
MPI_Bcast(f_vals.data(), n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
89+
continue;
90+
}
91+
92+
const int idx = global_data.index;
93+
const double mid = 0.5 * (x_vals[idx] + x_vals[idx - 1]);
94+
95+
double new_x = mid - ((f_vals[idx] - f_vals[idx - 1]) / (2.0 * m));
96+
97+
new_x = std::clamp(new_x, x_vals[idx - 1], x_vals[idx]);
98+
99+
x_vals.insert(x_vals.begin() + idx, new_x);
100+
f_vals.insert(f_vals.begin() + idx, f(new_x));
101+
102+
int n = static_cast<int>(x_vals.size());
103+
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
104+
MPI_Bcast(x_vals.data(), n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
105+
MPI_Bcast(f_vals.data(), n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
106+
}
107+
108+
GetOutput() = *std::ranges::min_element(f_vals);
109+
return true;
110+
}
111+
112+
bool TelnovStronginAlgorithmMPI::PostProcessingImpl() {
113+
return true;
114+
}
115+
116+
} // namespace telnov_strongin_algorithm

0 commit comments

Comments
 (0)