Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace timofeev_n_radix_batcher_sort_threads {

using InType = std::vector<int>;
using OutType = std::vector<int>;
// вход, выход, проверка, имя
// вход, выход, проверка, имя
using TestType = std::tuple<std::vector<int>, std::vector<int>, int, std::string>;
using BaseTask = ppc::task::Task<InType, OutType>;

Expand Down
30 changes: 30 additions & 0 deletions tasks/timofeev_n_radix_batcher_sort/omp/include/ops_omp.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include <vector>

#include "task/include/task.hpp"
#include "timofeev_n_radix_batcher_sort/common/include/common.hpp"

namespace timofeev_n_radix_batcher_sort_threads {

class TimofeevNRadixBatcherOMP : public BaseTask {
public:
static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() {
return ppc::task::TypeOfTask::kOMP;
}
explicit TimofeevNRadixBatcherOMP(const InType &in);

private:
bool ValidationImpl() override;
bool PreProcessingImpl() override;
bool RunImpl() override;
bool PostProcessingImpl() override;

static int Loggo(int inputa);
static void CompExch(int &a, int &b, int digit);
static void BubbleSort(std::vector<int> &arr, int digit, int left, int right);
static void ComparR(int &a, int &b);
static void OddEvenMerge(std::vector<int> &arr, int lft, int n);
};

} // namespace timofeev_n_radix_batcher_sort_threads
147 changes: 147 additions & 0 deletions tasks/timofeev_n_radix_batcher_sort/omp/src/ops_omp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#include "timofeev_n_radix_batcher_sort/omp/include/ops_omp.hpp"

#include <omp.h>

#include <algorithm>
#include <climits>
#include <cstddef>
#include <utility>
#include <vector>

#include "timofeev_n_radix_batcher_sort/common/include/common.hpp"

namespace timofeev_n_radix_batcher_sort_threads {

TimofeevNRadixBatcherOMP::TimofeevNRadixBatcherOMP(const InType &in) {
SetTypeOfTask(GetStaticTypeOfTask());
GetInput() = in;
GetOutput() = in;
}

void TimofeevNRadixBatcherOMP::CompExch(int &a, int &b, int digit) {
int b_r = b % (digit * 10) / digit;
int a_r = a % (digit * 10) / digit;
if (b_r < a_r) {
std::swap(a, b);
}
}

void TimofeevNRadixBatcherOMP::BubbleSort(std::vector<int> &arr, int digit, int left, int right) {
for (int i = left; i <= right; i++) {
for (int j = 0; j + 1 < right - left; j++) {
CompExch(arr[left + j], arr[left + j + 1], digit);
}
}
}

void TimofeevNRadixBatcherOMP::ComparR(int &a, int &b) {
if (a > b) {
std::swap(a, b);
}
}

void TimofeevNRadixBatcherOMP::OddEvenMerge(std::vector<int> &arr, int lft, int n) {
if (n <= 1) {
return;
}

int otstup = n / 2;
for (int i = 0; i < otstup; i += 1) {
if (arr[lft + i] > arr[lft + otstup + i]) {
std::swap(arr[lft + i], arr[lft + otstup + i]);
}
}

for (otstup = n / 4; otstup > 0; otstup /= 2) {
int h = otstup * 2;
for (int start = otstup; start + otstup < n; start += h) {
for (int i = 0; i < otstup; i += 1) {
ComparR(arr[lft + start + i], arr[lft + start + i + otstup]);
}
}
}
}

int TimofeevNRadixBatcherOMP::Loggo(int inputa) {
int count = 0;
while (inputa > 1) {
inputa /= 2;
count++;
}
return count;
}

bool TimofeevNRadixBatcherOMP::ValidationImpl() {
return GetInput().size() >= 2;
}

bool TimofeevNRadixBatcherOMP::PreProcessingImpl() {
return true;
}

bool TimofeevNRadixBatcherOMP::RunImpl() {
std::vector<int> in = GetInput();
int n = static_cast<int>(in.size());
int m = n;
while (n % 2 == 0) {
n /= 2;
}
if (n > 1) {
n = static_cast<int>(in.size());
int p = 1;
while (p < n) {
p *= 2;
}
n = p;
} else {
n = m;
}
int max_x = *(std::ranges::max_element(in.begin(), in.end()));
if (n != m) {
in.resize(n, max_x);
}
size_t n_thr = omp_get_max_threads();
size_t num_threads = 1;
while (num_threads * 2 <= n_thr && n / num_threads >= 4) {
num_threads *= 2;
}
std::vector<int> &r_in = in;
size_t n_n = n;
size_t m_m = m;
std::vector<int> &reff = GetInput();
#pragma omp parallel num_threads(num_threads) default(none) shared(r_in, max_x, n_n, num_threads, m_m, reff)
{
size_t t_n = omp_get_thread_num();
size_t piece = n_n / num_threads;
for (int k = 1; k <= max_x; k *= 10) {
BubbleSort(r_in, k, static_cast<int>(piece * t_n), static_cast<int>((piece * t_n) + piece)); // [left; right)
}
#pragma omp barrier
size_t c_p = piece * 2;
for (; c_p <= n_n; c_p *= 2) {
#pragma omp for
for (size_t i = 0; i < n_n; i += c_p) {
OddEvenMerge(r_in, static_cast<int>(i), static_cast<int>(c_p));
}
#pragma omp barrier
}
if (t_n == 0 && m_m != n_n) {
r_in.resize(m_m);
}
#pragma omp barrier
#pragma omp for
for (size_t i = 0; i < r_in.size(); i++) {
reff[i] = r_in[i];
}
#pragma omp barrier
}

GetOutput() = reff;
return true;
}

bool TimofeevNRadixBatcherOMP::PostProcessingImpl() {
return true;
}

} // namespace timofeev_n_radix_batcher_sort_threads
35 changes: 35 additions & 0 deletions tasks/timofeev_n_radix_batcher_sort/tbb/include/ops_tbb.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include <cstddef>
#include <vector>

#include "task/include/task.hpp"
#include "timofeev_n_radix_batcher_sort/common/include/common.hpp"

namespace timofeev_n_radix_batcher_sort_threads {

class TimofeevNRadixBatcherTBB : public BaseTask {
public:
static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() {
return ppc::task::TypeOfTask::kTBB;
}
explicit TimofeevNRadixBatcherTBB(const InType &in);

private:
bool ValidationImpl() override;
bool PreProcessingImpl() override;
bool RunImpl() override;
bool PostProcessingImpl() override;

static int Loggo(int inputa);
static void CompExch(int &a, int &b, int digit);
static void BubbleSort(std::vector<int> &arr, int digit, int left, int right);
static void ComparR(int &a, int &b);
static void OddEvenMerge(std::vector<int> &arr, int lft, int n);

void PrepAux(int &n, int &m, std::vector<int> &in, int &max_x, size_t &num_threads, size_t &n_thr);
static void HandleTBB(size_t &num_threads, size_t &n_n, size_t &m_m, int &max_x, std::vector<int> &reff,
std::vector<int> &r_in);
};

} // namespace timofeev_n_radix_batcher_sort_threads
173 changes: 173 additions & 0 deletions tasks/timofeev_n_radix_batcher_sort/tbb/src/ops_tbb.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#include "timofeev_n_radix_batcher_sort/tbb/include/ops_tbb.hpp"

#include <tbb/tbb.h>

#include <algorithm>
#include <climits>
#include <cstddef>
#include <utility>
#include <vector>

#include "timofeev_n_radix_batcher_sort/common/include/common.hpp"

namespace timofeev_n_radix_batcher_sort_threads {

TimofeevNRadixBatcherTBB::TimofeevNRadixBatcherTBB(const InType &in) {
SetTypeOfTask(GetStaticTypeOfTask());
GetInput() = in;
GetOutput() = in;
}

void TimofeevNRadixBatcherTBB::CompExch(int &a, int &b, int digit) {
int b_r = b % (digit * 10) / digit;
int a_r = a % (digit * 10) / digit;
if (b_r < a_r) {
std::swap(a, b);
}
}

void TimofeevNRadixBatcherTBB::BubbleSort(std::vector<int> &arr, int digit, int left, int right) {
for (int i = left; i <= right; i++) {
for (int j = 0; j + 1 < right - left; j++) {
CompExch(arr[left + j], arr[left + j + 1], digit);
}
}
}

void TimofeevNRadixBatcherTBB::ComparR(int &a, int &b) {
if (a > b) {
std::swap(a, b);
}
}

void TimofeevNRadixBatcherTBB::OddEvenMerge(std::vector<int> &arr, int lft, int n) {
if (n <= 1) {
return;
}

int otstup = n / 2;
for (int i = 0; i < otstup; i += 1) {
if (arr[lft + i] > arr[lft + otstup + i]) {
std::swap(arr[lft + i], arr[lft + otstup + i]);
}
}

for (otstup = n / 4; otstup > 0; otstup /= 2) {
int h = otstup * 2;
for (int start = otstup; start + otstup < n; start += h) {
for (int i = 0; i < otstup; i += 1) {
ComparR(arr[lft + start + i], arr[lft + start + i + otstup]);
}
}
}
}

int TimofeevNRadixBatcherTBB::Loggo(int inputa) {
int count = 0;
while (inputa > 1) {
inputa /= 2;
count++;
}
return count;
}

bool TimofeevNRadixBatcherTBB::ValidationImpl() {
return GetInput().size() >= 2;
}

bool TimofeevNRadixBatcherTBB::PreProcessingImpl() {
return true;
}

void TimofeevNRadixBatcherTBB::PrepAux(int &n, int &m, std::vector<int> &in, int &max_x, size_t &num_threads,
size_t &n_thr) {
in = GetInput();
n = static_cast<int>(in.size());
m = n;

while (n % 2 == 0) {
n /= 2;
}
if (n > 1) {
n = static_cast<int>(in.size());
int p = 1;
while (p < n) {
p *= 2;
}
n = p;
} else {
n = m;
}

max_x = *(std::ranges::max_element(in.begin(), in.end()));
if (n != m) {
in.resize(n, max_x);
}
// tbb
n_thr = tbb::this_task_arena::max_concurrency();
num_threads = 1;
while (num_threads * 2 <= n_thr && n / num_threads >= 4) {
num_threads *= 2;
}
}

void TimofeevNRadixBatcherTBB::HandleTBB(size_t &num_threads, size_t &n_n, size_t &m_m, int &max_x,
std::vector<int> &reff, std::vector<int> &r_in) {
tbb::task_arena arena(static_cast<int>(num_threads));
arena.execute([&] {
size_t piece = 0;
tbb::parallel_for(tbb::blocked_range<size_t>(0, num_threads), [&](const tbb::blocked_range<size_t> &range) {
size_t t_n = range.begin();
piece = n_n / num_threads;
for (int k = 1; k <= max_x; k *= 10) {
BubbleSort(r_in, k, static_cast<int>(piece * t_n), static_cast<int>((piece * t_n) + piece));
}
});

size_t c_p = piece * 2;
for (; c_p <= n_n; c_p *= 2) {
tbb::parallel_for(tbb::blocked_range<size_t>(0, n_n, c_p), [&](const tbb::blocked_range<size_t> &range) {
for (size_t i = range.begin(); i < range.end(); i += c_p) {
OddEvenMerge(r_in, static_cast<int>(i), static_cast<int>(c_p));
}
});
}

if (m_m != n_n && tbb::this_task_arena::current_thread_index() == 0) {
r_in.resize(m_m);
}

tbb::parallel_for(tbb::blocked_range<size_t>(0, r_in.size()), [&](const tbb::blocked_range<size_t> &range) {
for (size_t i = range.begin(); i < range.end(); ++i) {
reff[i] = r_in[i];
}
});
});
}

bool TimofeevNRadixBatcherTBB::RunImpl() {
std::vector<int> in;
int n = 0;
int m = 0;
int max_x = 0;
size_t n_thr = 0; // = tbb::this_task_arena::max_concurrency();
size_t num_threads = 0;

PrepAux(n, m, in, max_x, num_threads, n_thr);

std::vector<int> &r_in = in;
size_t n_n = n;
size_t m_m = m;
std::vector<int> &reff = GetInput();

HandleTBB(num_threads, n_n, m_m, max_x, reff, r_in);
// tbb
GetOutput() = reff;
return true;
}

bool TimofeevNRadixBatcherTBB::PostProcessingImpl() {
return true;
}

} // namespace timofeev_n_radix_batcher_sort_threads
Loading
Loading