Skip to content

Commit

Permalink
Сдобнов Владимир Задача 3. Вариант 15. Четно-нечетная сортировка слия…
Browse files Browse the repository at this point in the history
…нием Бетчера (#783)

Входные данные:
Для последовательного алгоритма: вектор и его размер равный степени
двойки
Для параллельного: вектор и его размер
Описание параллельного алгоритма:
Делим вектор между потоками. Каждый поток сортирует свои данные, после
чего данные из потоков сливаются.
Процесс слияния: Процесс получает данные от следующего за ним процесса,
объединяет их со своими и сортирует, затем возвращает вторую половину
полученного вектора обратно. Пары выбираются поочередно, сначала (0,1),
(2,3), (4,5) и тд, затем (1,2), (3,4), (5,6). Число слияний равно числу
потоков.
После прохождения слияний все данные собираются в 0 потоке.
  • Loading branch information
VladimirSdobnov authored Dec 29, 2024
1 parent 1c4a7af commit 27135fa
Show file tree
Hide file tree
Showing 8 changed files with 860 additions and 0 deletions.
217 changes: 217 additions & 0 deletions tasks/mpi/Sdobnov_V_mergesort_Betcher/func_tests/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
#include <gtest/gtest.h>

#include <boost/mpi/communicator.hpp>
#include <boost/mpi/environment.hpp>
#include <vector>

#include "mpi/Sdobnov_V_mergesort_Betcher/include/ops_mpi.hpp"

TEST(Sdobnov_V_mergesort_Betcher_par, InvalidInputCount) {
boost::mpi::communicator world;

int size = 10;
std::vector<int> res(size, 0);
std::vector<int> input = {2, 1, 0, 3, 9, 7, 2, 6, 4, 8};
std::vector<int> expected_res = {0, 1, 2, 2, 3, 4, 6, 7, 8, 9};

std::shared_ptr<ppc::core::TaskData> taskDataPar = std::make_shared<ppc::core::TaskData>();
if (world.rank() == 0) {
taskDataPar->inputs.emplace_back(reinterpret_cast<uint8_t *>(input.data()));
taskDataPar->outputs_count.emplace_back(size);
taskDataPar->outputs.emplace_back(reinterpret_cast<uint8_t *>(res.data()));
}

Sdobnov_V_mergesort_Betcher_par::MergesortBetcherPar test(taskDataPar);
if (world.rank() == 0) {
ASSERT_FALSE(test.validation());
}
}

TEST(Sdobnov_V_mergesort_Betcher_par, InvalidInput) {
boost::mpi::communicator world;

int size = 10;
std::vector<int> res(size, 0);
std::vector<int> input = {2, 1, 0, 3, 9, 7, 2, 6, 4, 8};
std::vector<int> expected_res = {0, 1, 2, 2, 3, 4, 6, 7, 8, 9};

std::shared_ptr<ppc::core::TaskData> taskDataPar = std::make_shared<ppc::core::TaskData>();
if (world.rank() == 0) {
taskDataPar->inputs_count.emplace_back(size);
taskDataPar->outputs_count.emplace_back(size);
taskDataPar->outputs.emplace_back(reinterpret_cast<uint8_t *>(res.data()));
}

Sdobnov_V_mergesort_Betcher_par::MergesortBetcherPar test(taskDataPar);

if (world.rank() == 0) {
ASSERT_FALSE(test.validation());
}
}

TEST(Sdobnov_V_mergesort_Betcher_par, InvalidOutputCount) {
boost::mpi::communicator world;

int size = 10;
std::vector<int> res(size, 0);
std::vector<int> input = {2, 1, 0, 3, 9, 7, 2, 6, 4, 8};
std::vector<int> expected_res = {0, 1, 2, 2, 3, 4, 6, 7, 8, 9};

std::shared_ptr<ppc::core::TaskData> taskDataPar = std::make_shared<ppc::core::TaskData>();

if (world.rank() == 0) {
taskDataPar->inputs_count.emplace_back(size);
taskDataPar->inputs.emplace_back(reinterpret_cast<uint8_t *>(input.data()));
taskDataPar->outputs.emplace_back(reinterpret_cast<uint8_t *>(res.data()));
}

Sdobnov_V_mergesort_Betcher_par::MergesortBetcherPar test(taskDataPar);

if (world.rank() == 0) {
ASSERT_FALSE(test.validation());
}
}

TEST(Sdobnov_V_mergesort_Betcher_par, InvalidOutput) {
boost::mpi::communicator world;

int size = 10;
std::vector<int> res(size, 0);
std::vector<int> input = {2, 1, 0, 3, 9, 7, 2, 6, 4, 8};
std::vector<int> expected_res = {0, 1, 2, 2, 3, 4, 6, 7, 8, 9};

std::shared_ptr<ppc::core::TaskData> taskDataPar = std::make_shared<ppc::core::TaskData>();
if (world.rank() == 0) {
taskDataPar->inputs_count.emplace_back(size);
taskDataPar->inputs.emplace_back(reinterpret_cast<uint8_t *>(input.data()));
taskDataPar->outputs_count.emplace_back(size);
}

Sdobnov_V_mergesort_Betcher_par::MergesortBetcherPar test(taskDataPar);

if (world.rank() == 0) {
ASSERT_FALSE(test.validation());
}
}

TEST(Sdobnov_V_mergesort_Betcher_par, SortTest8) {
boost::mpi::communicator world;

int size = 8;
std::vector<int> res(size, 0);
std::vector<int> input = {2, 8, 3, 9, 5, 6, 4, 0};
std::vector<int> expected_res = {0, 2, 3, 4, 5, 6, 8, 9};
std::shared_ptr<ppc::core::TaskData> taskDataPar = std::make_shared<ppc::core::TaskData>();

if (world.rank() == 0) {
taskDataPar->inputs_count.emplace_back(size);
taskDataPar->inputs.emplace_back(reinterpret_cast<uint8_t *>(input.data()));
taskDataPar->outputs_count.emplace_back(size);
taskDataPar->outputs.emplace_back(reinterpret_cast<uint8_t *>(res.data()));
}

Sdobnov_V_mergesort_Betcher_par::MergesortBetcherPar test(taskDataPar);
test.validation();
test.pre_processing();
test.run();
test.post_processing();

if (world.rank() == 0) {
for (int i = 0; i < size; i++) {
ASSERT_EQ(res[i], expected_res[i]);
}
}
}

TEST(Sdobnov_V_mergesort_Betcher_par, SortTestRand16) {
boost::mpi::communicator world;

int size = 16;
std::vector<int> res(size, 0);
std::vector<int> input = Sdobnov_V_mergesort_Betcher_par::generate_random_vector(size, 0, 1000);

std::shared_ptr<ppc::core::TaskData> taskDataPar = std::make_shared<ppc::core::TaskData>();

if (world.rank() == 0) {
taskDataPar->inputs_count.emplace_back(size);
taskDataPar->inputs.emplace_back(reinterpret_cast<uint8_t *>(input.data()));
taskDataPar->outputs_count.emplace_back(size);
taskDataPar->outputs.emplace_back(reinterpret_cast<uint8_t *>(res.data()));
}

Sdobnov_V_mergesort_Betcher_par::MergesortBetcherPar test(taskDataPar);
test.validation();
test.pre_processing();
test.run();
test.post_processing();

if (world.rank() == 0) {
std::vector<int> expected_res = input;
std::sort(expected_res.begin(), expected_res.end());
for (int i = 0; i < size; i++) {
ASSERT_EQ(res[i], expected_res[i]);
}
}
}

TEST(Sdobnov_V_mergesort_Betcher_par, SortTestRand32) {
boost::mpi::communicator world;

int size = 32;
std::vector<int> res(size, 0);
std::vector<int> input = Sdobnov_V_mergesort_Betcher_par::generate_random_vector(size, 0, 1000);

std::shared_ptr<ppc::core::TaskData> taskDataPar = std::make_shared<ppc::core::TaskData>();

if (world.rank() == 0) {
taskDataPar->inputs_count.emplace_back(size);
taskDataPar->inputs.emplace_back(reinterpret_cast<uint8_t *>(input.data()));
taskDataPar->outputs_count.emplace_back(size);
taskDataPar->outputs.emplace_back(reinterpret_cast<uint8_t *>(res.data()));
}

Sdobnov_V_mergesort_Betcher_par::MergesortBetcherPar test(taskDataPar);
test.validation();
test.pre_processing();
test.run();
test.post_processing();

if (world.rank() == 0) {
std::vector<int> expected_res = input;
std::sort(expected_res.begin(), expected_res.end());
for (int i = 0; i < size; i++) {
ASSERT_EQ(res[i], expected_res[i]);
}
}
}

TEST(Sdobnov_V_mergesort_Betcher_par, SortTestRand64) {
boost::mpi::communicator world;

int size = 64;
std::vector<int> res(size, 0);
std::vector<int> input = Sdobnov_V_mergesort_Betcher_par::generate_random_vector(size, 0, 1000);

std::shared_ptr<ppc::core::TaskData> taskDataPar = std::make_shared<ppc::core::TaskData>();

if (world.rank() == 0) {
taskDataPar->inputs_count.emplace_back(size);
taskDataPar->inputs.emplace_back(reinterpret_cast<uint8_t *>(input.data()));
taskDataPar->outputs_count.emplace_back(size);
taskDataPar->outputs.emplace_back(reinterpret_cast<uint8_t *>(res.data()));
}

Sdobnov_V_mergesort_Betcher_par::MergesortBetcherPar test(taskDataPar);
test.validation();
test.pre_processing();
test.run();
test.post_processing();

if (world.rank() == 0) {
std::vector<int> expected_res = input;
std::sort(expected_res.begin(), expected_res.end());
for (int i = 0; i < size; i++) {
ASSERT_EQ(res[i], expected_res[i]);
}
}
}
32 changes: 32 additions & 0 deletions tasks/mpi/Sdobnov_V_mergesort_Betcher/include/ops_mpi.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2024 Sdobnov Vladimir
#pragma once
#include <gtest/gtest.h>

#include <boost/mpi/collectives.hpp>
#include <boost/mpi/communicator.hpp>
#include <vector>

#include "core/task/include/task.hpp"

namespace Sdobnov_V_mergesort_Betcher_par {

std::vector<int> generate_random_vector(int size, int lower_bound = 0, int upper_bound = 50);
int partition(std::vector<int>& vec, int low, int high);
void quickSortIterative(std::vector<int>& vec, int low, int high);

class MergesortBetcherPar : public ppc::core::Task {
public:
explicit MergesortBetcherPar(std::shared_ptr<ppc::core::TaskData> taskData_) : Task(std::move(taskData_)) {}
bool pre_processing() override;
bool validation() override;
bool run() override;
bool post_processing() override;

private:
std::vector<int> input_;
int size_;
std::vector<int> local_vec_;

boost::mpi::communicator world;
};
} // namespace Sdobnov_V_mergesort_Betcher_par
87 changes: 87 additions & 0 deletions tasks/mpi/Sdobnov_V_mergesort_Betcher/perf_tests/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include <gtest/gtest.h>

#include <boost/mpi/timer.hpp>
#include <random>
#include <vector>

#include "core/perf/include/perf.hpp"
#include "mpi/Sdobnov_V_mergesort_Betcher/include/ops_mpi.hpp"

TEST(Sdobnov_V_mergesort_Betcher_par, test_pipeline_run) {
boost::mpi::communicator world;

long unsigned int size = 4096;
std::vector<int> res(size, 0);
std::vector<int> input = Sdobnov_V_mergesort_Betcher_par::generate_random_vector(size, 0, 1000);

std::shared_ptr<ppc::core::TaskData> taskDataPar = std::make_shared<ppc::core::TaskData>();
if (world.rank() == 0) {
taskDataPar->inputs_count.emplace_back(size);
taskDataPar->inputs.emplace_back(reinterpret_cast<uint8_t *>(input.data()));
taskDataPar->outputs_count.emplace_back(size);
taskDataPar->outputs.emplace_back(reinterpret_cast<uint8_t *>(res.data()));
}

auto test = std::make_shared<Sdobnov_V_mergesort_Betcher_par::MergesortBetcherPar>(taskDataPar);
test->validation();
test->pre_processing();
test->run();
test->post_processing();

auto perfAttr = std::make_shared<ppc::core::PerfAttr>();
perfAttr->num_running = 10;
const auto t0 = std::chrono::high_resolution_clock::now();
perfAttr->current_timer = [&] {
auto current_time_point = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time_point - t0).count();
return static_cast<double>(duration) * 1e-9;
};
auto perfResults = std::make_shared<ppc::core::PerfResults>();
auto perfAnalyzer = std::make_shared<ppc::core::Perf>(test);
perfAnalyzer->pipeline_run(perfAttr, perfResults);
ppc::core::Perf::print_perf_statistic(perfResults);

if (world.rank() == 0) {
ASSERT_EQ(res.size(), size);
}
}

TEST(Sdobnov_V_mergesort_Betcher_par, test_task_run) {
boost::mpi::communicator world;

long unsigned int size = 4096;
std::vector<int> res(size, 0);
std::vector<int> input = Sdobnov_V_mergesort_Betcher_par::generate_random_vector(size, 0, 1000);

std::shared_ptr<ppc::core::TaskData> taskDataPar = std::make_shared<ppc::core::TaskData>();

if (world.rank() == 0) {
taskDataPar->inputs_count.emplace_back(size);
taskDataPar->inputs.emplace_back(reinterpret_cast<uint8_t *>(input.data()));
taskDataPar->outputs_count.emplace_back(size);
taskDataPar->outputs.emplace_back(reinterpret_cast<uint8_t *>(res.data()));
}

auto test = std::make_shared<Sdobnov_V_mergesort_Betcher_par::MergesortBetcherPar>(taskDataPar);
test->validation();
test->pre_processing();
test->run();
test->post_processing();

auto perfAttr = std::make_shared<ppc::core::PerfAttr>();
perfAttr->num_running = 10;
const auto t0 = std::chrono::high_resolution_clock::now();
perfAttr->current_timer = [&] {
auto current_time_point = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time_point - t0).count();
return static_cast<double>(duration) * 1e-9;
};
auto perfResults = std::make_shared<ppc::core::PerfResults>();
auto perfAnalyzer = std::make_shared<ppc::core::Perf>(test);
perfAnalyzer->task_run(perfAttr, perfResults);
ppc::core::Perf::print_perf_statistic(perfResults);

if (world.rank() == 0) {
ASSERT_EQ(res.size(), size);
}
}
Loading

0 comments on commit 27135fa

Please sign in to comment.