From 1c8f1cabd75432b448f8e3a8114b694266463b0e Mon Sep 17 00:00:00 2001 From: TepidmishA Date: Wed, 15 Apr 2026 20:06:00 +0300 Subject: [PATCH 1/4] implement stl --- .../stl/include/ops_stl.hpp | 37 +++ .../stl/src/ops_stl.cpp | 210 ++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 tasks/perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp create mode 100644 tasks/perepelkin_i_convex_hull_graham_scan/stl/src/ops_stl.cpp diff --git a/tasks/perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp b/tasks/perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp new file mode 100644 index 000000000..f10468270 --- /dev/null +++ b/tasks/perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + +#include "perepelkin_i_convex_hull_graham_scan/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace perepelkin_i_convex_hull_graham_scan { + +class PerepelkinIConvexHullGrahamScanSTL : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSTL; + } + explicit PerepelkinIConvexHullGrahamScanSTL(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + bool PostProcessingImpl() override; + + static size_t FindPivotParallel(const std::vector> &pts); + static void ParallelSort(std::vector> &data, const std::pair &pivot); + + static void HullConstruction(std::vector> &hull, + const std::vector> &pts, + const std::pair &pivot); + static bool AngleCmp(const std::pair &a, const std::pair &b, + const std::pair &pivot); + static double Orientation(const std::pair &p, const std::pair &q, + const std::pair &r); +}; + +} // namespace perepelkin_i_convex_hull_graham_scan diff --git a/tasks/perepelkin_i_convex_hull_graham_scan/stl/src/ops_stl.cpp b/tasks/perepelkin_i_convex_hull_graham_scan/stl/src/ops_stl.cpp new file mode 100644 index 000000000..ffe19f1e9 --- /dev/null +++ b/tasks/perepelkin_i_convex_hull_graham_scan/stl/src/ops_stl.cpp @@ -0,0 +1,210 @@ +#include "perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp" + +#include +#include +#include +#include +#include +#include + +#include "perepelkin_i_convex_hull_graham_scan/common/include/common.hpp" +#include "util/include/util.hpp" + +namespace perepelkin_i_convex_hull_graham_scan { + +PerepelkinIConvexHullGrahamScanSTL::PerepelkinIConvexHullGrahamScanSTL(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = std::vector>(); +} + +bool PerepelkinIConvexHullGrahamScanSTL::ValidationImpl() { + return GetOutput().empty(); +} + +bool PerepelkinIConvexHullGrahamScanSTL::PreProcessingImpl() { + return true; +} + +bool PerepelkinIConvexHullGrahamScanSTL::RunImpl() { + const auto &data = GetInput(); + + if (data.size() < 2) { + GetOutput() = data; + return true; + } + + std::vector> pts = data; + + // Find pivot + size_t pivot_idx = FindPivotParallel(pts); + + std::pair pivot = pts[pivot_idx]; + pts.erase(pts.begin() + static_cast(pivot_idx)); + + // Parallel sorting + ParallelSort(pts, pivot); + + // Sequential hull construction + std::vector> hull; + HullConstruction(hull, pts, pivot); + + GetOutput() = std::move(hull); + return true; +} + +size_t PerepelkinIConvexHullGrahamScanSTL::FindPivotParallel( + const std::vector> &pts) { + + size_t pivot_idx = 0; + const int threads = ppc::util::GetNumThreads(); + const size_t block_size = pts.size() / threads; + + std::vector local_idx(threads, 0); + + // Parallel local pivot finding + { + std::vector workers; + + for (int tid = 0; tid < threads; tid++) { + workers.emplace_back([&, tid]() { + size_t local = pivot_idx; + + size_t start = tid * block_size; + size_t end = (tid + 1) * block_size; + + if (start == 0) start = 1; + + for (size_t i = start; i < end; i++) { + if (pts[i].second < pts[local].second || + (pts[i].second == pts[local].second && + pts[i].first < pts[local].first)) { + local = i; + } + } + + local_idx[tid] = local; + }); + } + } + + // Reduction + for (int tid = 0; tid < threads; tid++) { + size_t i = local_idx[tid]; + + if (pts[i].second < pts[pivot_idx].second || + (pts[i].second == pts[pivot_idx].second && + pts[i].first < pts[pivot_idx].first)) { + pivot_idx = i; + } + } + + return pivot_idx; +} + +void PerepelkinIConvexHullGrahamScanSTL::ParallelSort( + std::vector> &data, + const std::pair &pivot) { + + const int threads = ppc::util::GetNumThreads(); + const size_t block_size = data.size() / threads; + + std::vector start(threads + 1); + for (int i = 0; i <= threads; i++) { + start[i] = static_cast(i * block_size); + } + + // Parallel local sorting + { + std::vector workers; + + for (int tid = 0; tid < threads; tid++) { + workers.emplace_back([&, tid]() { + std::sort(data.begin() + start[tid], + data.begin() + start[tid + 1], + [&](const auto &a, const auto &b) { + return AngleCmp(a, b, pivot); + }); + }); + } + } + + // Merge sorted segments + for (int size = 1; size < threads; size *= 2) { + std::vector workers; + + for (int i = 0; i < threads; i += 2 * size) { + if (i + size >= threads) { + continue; + } + + workers.emplace_back([&, i, size]() { + int left = start[i]; + int mid = start[i + size]; + int right = start[std::min(i + (2 * size), threads)]; + + std::inplace_merge( + data.begin() + left, + data.begin() + mid, + data.begin() + right, + [&](const auto &a, const auto &b) { + return AngleCmp(a, b, pivot); + }); + }); + } + } +} + +void perepelkin_i_convex_hull_graham_scan::PerepelkinIConvexHullGrahamScanSTL::HullConstruction( + std::vector> &hull, const std::vector> &pts, + const std::pair &pivot) { + hull.reserve(pts.size() + 1); + + hull.push_back(pivot); + hull.push_back(pts[0]); + + for (size_t i = 1; i < pts.size(); i++) { + while (hull.size() >= 2 && Orientation(hull[hull.size() - 2], hull[hull.size() - 1], pts[i]) <= 0) { + hull.pop_back(); + } + + hull.push_back(pts[i]); + } +} + +double PerepelkinIConvexHullGrahamScanSTL::Orientation(const std::pair &p, + const std::pair &q, + const std::pair &r) { + double val = ((q.first - p.first) * (r.second - p.second)) - ((q.second - p.second) * (r.first - p.first)); + + if (std::abs(val) < 1e-9) { + return 0.0; + } + + return val; +} + +bool PerepelkinIConvexHullGrahamScanSTL::AngleCmp(const std::pair &a, + const std::pair &b, + const std::pair &pivot) { + double dx1 = a.first - pivot.first; + double dy1 = a.second - pivot.second; + double dx2 = b.first - pivot.first; + double dy2 = b.second - pivot.second; + + double cross = (dx1 * dy2) - (dy1 * dx2); + + if (std::abs(cross) < 1e-9) { + double dist1 = (dx1 * dx1) + (dy1 * dy1); + double dist2 = (dx2 * dx2) + (dy2 * dy2); + return dist1 < dist2; + } + + return cross > 0; +} + +bool PerepelkinIConvexHullGrahamScanSTL::PostProcessingImpl() { + return true; +} + +} // namespace perepelkin_i_convex_hull_graham_scan From ac23f7725e516d5c9a7c8e9aebd6328aa6acb190 Mon Sep 17 00:00:00 2001 From: TepidmishA Date: Wed, 15 Apr 2026 20:06:17 +0300 Subject: [PATCH 2/4] update tests --- .../tests/functional/main.cpp | 3 +++ .../tests/performance/main.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/tasks/perepelkin_i_convex_hull_graham_scan/tests/functional/main.cpp b/tasks/perepelkin_i_convex_hull_graham_scan/tests/functional/main.cpp index 8d96bf950..a16af5966 100644 --- a/tasks/perepelkin_i_convex_hull_graham_scan/tests/functional/main.cpp +++ b/tasks/perepelkin_i_convex_hull_graham_scan/tests/functional/main.cpp @@ -10,6 +10,7 @@ #include "perepelkin_i_convex_hull_graham_scan/omp/include/ops_omp.hpp" #include "perepelkin_i_convex_hull_graham_scan/seq/include/ops_seq.hpp" #include "perepelkin_i_convex_hull_graham_scan/tbb/include/ops_tbb.hpp" +#include "perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp" #include "util/include/func_test_util.hpp" #include "util/include/util.hpp" @@ -87,6 +88,8 @@ const auto kTestTasksList = std::tuple_cat(ppc::util::AddFuncTask( kTestParam, PPC_SETTINGS_perepelkin_i_convex_hull_graham_scan), ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_perepelkin_i_convex_hull_graham_scan), + ppc::util::AddFuncTask( kTestParam, PPC_SETTINGS_perepelkin_i_convex_hull_graham_scan)); const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); diff --git a/tasks/perepelkin_i_convex_hull_graham_scan/tests/performance/main.cpp b/tasks/perepelkin_i_convex_hull_graham_scan/tests/performance/main.cpp index bda78bac9..68ce9592d 100644 --- a/tasks/perepelkin_i_convex_hull_graham_scan/tests/performance/main.cpp +++ b/tasks/perepelkin_i_convex_hull_graham_scan/tests/performance/main.cpp @@ -13,6 +13,7 @@ #include "perepelkin_i_convex_hull_graham_scan/omp/include/ops_omp.hpp" #include "perepelkin_i_convex_hull_graham_scan/seq/include/ops_seq.hpp" #include "perepelkin_i_convex_hull_graham_scan/tbb/include/ops_tbb.hpp" +#include "perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp" #include "task/include/task.hpp" #include "util/include/perf_test_util.hpp" @@ -78,6 +79,8 @@ const auto kAllPerfTasks = std::tuple_cat(ppc::util::MakeAllPerfTasks( PPC_SETTINGS_perepelkin_i_convex_hull_graham_scan), ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_perepelkin_i_convex_hull_graham_scan), + ppc::util::MakeAllPerfTasks( PPC_SETTINGS_perepelkin_i_convex_hull_graham_scan)); const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); From 58ceb8c8d0893ef9e293dc09c24b1ab583cbeb51 Mon Sep 17 00:00:00 2001 From: TepidmishA Date: Wed, 15 Apr 2026 20:10:24 +0300 Subject: [PATCH 3/4] fix code style --- .../stl/src/ops_stl.cpp | 38 +++++++------------ .../tests/functional/main.cpp | 2 +- .../tests/performance/main.cpp | 2 +- 3 files changed, 15 insertions(+), 27 deletions(-) diff --git a/tasks/perepelkin_i_convex_hull_graham_scan/stl/src/ops_stl.cpp b/tasks/perepelkin_i_convex_hull_graham_scan/stl/src/ops_stl.cpp index ffe19f1e9..75762f65c 100644 --- a/tasks/perepelkin_i_convex_hull_graham_scan/stl/src/ops_stl.cpp +++ b/tasks/perepelkin_i_convex_hull_graham_scan/stl/src/ops_stl.cpp @@ -3,9 +3,9 @@ #include #include #include +#include #include #include -#include #include "perepelkin_i_convex_hull_graham_scan/common/include/common.hpp" #include "util/include/util.hpp" @@ -53,9 +53,7 @@ bool PerepelkinIConvexHullGrahamScanSTL::RunImpl() { return true; } -size_t PerepelkinIConvexHullGrahamScanSTL::FindPivotParallel( - const std::vector> &pts) { - +size_t PerepelkinIConvexHullGrahamScanSTL::FindPivotParallel(const std::vector> &pts) { size_t pivot_idx = 0; const int threads = ppc::util::GetNumThreads(); const size_t block_size = pts.size() / threads; @@ -73,12 +71,13 @@ size_t PerepelkinIConvexHullGrahamScanSTL::FindPivotParallel( size_t start = tid * block_size; size_t end = (tid + 1) * block_size; - if (start == 0) start = 1; + if (start == 0) { + start = 1; + } for (size_t i = start; i < end; i++) { if (pts[i].second < pts[local].second || - (pts[i].second == pts[local].second && - pts[i].first < pts[local].first)) { + (pts[i].second == pts[local].second && pts[i].first < pts[local].first)) { local = i; } } @@ -93,8 +92,7 @@ size_t PerepelkinIConvexHullGrahamScanSTL::FindPivotParallel( size_t i = local_idx[tid]; if (pts[i].second < pts[pivot_idx].second || - (pts[i].second == pts[pivot_idx].second && - pts[i].first < pts[pivot_idx].first)) { + (pts[i].second == pts[pivot_idx].second && pts[i].first < pts[pivot_idx].first)) { pivot_idx = i; } } @@ -102,10 +100,8 @@ size_t PerepelkinIConvexHullGrahamScanSTL::FindPivotParallel( return pivot_idx; } -void PerepelkinIConvexHullGrahamScanSTL::ParallelSort( - std::vector> &data, - const std::pair &pivot) { - +void PerepelkinIConvexHullGrahamScanSTL::ParallelSort(std::vector> &data, + const std::pair &pivot) { const int threads = ppc::util::GetNumThreads(); const size_t block_size = data.size() / threads; @@ -120,11 +116,8 @@ void PerepelkinIConvexHullGrahamScanSTL::ParallelSort( for (int tid = 0; tid < threads; tid++) { workers.emplace_back([&, tid]() { - std::sort(data.begin() + start[tid], - data.begin() + start[tid + 1], - [&](const auto &a, const auto &b) { - return AngleCmp(a, b, pivot); - }); + std::sort(data.begin() + start[tid], data.begin() + start[tid + 1], + [&](const auto &a, const auto &b) { return AngleCmp(a, b, pivot); }); }); } } @@ -143,13 +136,8 @@ void PerepelkinIConvexHullGrahamScanSTL::ParallelSort( int mid = start[i + size]; int right = start[std::min(i + (2 * size), threads)]; - std::inplace_merge( - data.begin() + left, - data.begin() + mid, - data.begin() + right, - [&](const auto &a, const auto &b) { - return AngleCmp(a, b, pivot); - }); + std::inplace_merge(data.begin() + left, data.begin() + mid, data.begin() + right, + [&](const auto &a, const auto &b) { return AngleCmp(a, b, pivot); }); }); } } diff --git a/tasks/perepelkin_i_convex_hull_graham_scan/tests/functional/main.cpp b/tasks/perepelkin_i_convex_hull_graham_scan/tests/functional/main.cpp index a16af5966..82ffcae9c 100644 --- a/tasks/perepelkin_i_convex_hull_graham_scan/tests/functional/main.cpp +++ b/tasks/perepelkin_i_convex_hull_graham_scan/tests/functional/main.cpp @@ -9,8 +9,8 @@ #include "perepelkin_i_convex_hull_graham_scan/common/include/common.hpp" #include "perepelkin_i_convex_hull_graham_scan/omp/include/ops_omp.hpp" #include "perepelkin_i_convex_hull_graham_scan/seq/include/ops_seq.hpp" -#include "perepelkin_i_convex_hull_graham_scan/tbb/include/ops_tbb.hpp" #include "perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp" +#include "perepelkin_i_convex_hull_graham_scan/tbb/include/ops_tbb.hpp" #include "util/include/func_test_util.hpp" #include "util/include/util.hpp" diff --git a/tasks/perepelkin_i_convex_hull_graham_scan/tests/performance/main.cpp b/tasks/perepelkin_i_convex_hull_graham_scan/tests/performance/main.cpp index 68ce9592d..469e65ccf 100644 --- a/tasks/perepelkin_i_convex_hull_graham_scan/tests/performance/main.cpp +++ b/tasks/perepelkin_i_convex_hull_graham_scan/tests/performance/main.cpp @@ -12,8 +12,8 @@ #include "perepelkin_i_convex_hull_graham_scan/common/include/common.hpp" #include "perepelkin_i_convex_hull_graham_scan/omp/include/ops_omp.hpp" #include "perepelkin_i_convex_hull_graham_scan/seq/include/ops_seq.hpp" -#include "perepelkin_i_convex_hull_graham_scan/tbb/include/ops_tbb.hpp" #include "perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp" +#include "perepelkin_i_convex_hull_graham_scan/tbb/include/ops_tbb.hpp" #include "task/include/task.hpp" #include "util/include/perf_test_util.hpp" From 739f00a06afb6ec37f7f27061e5e3fc81bc64906 Mon Sep 17 00:00:00 2001 From: TepidmishA Date: Wed, 15 Apr 2026 21:21:36 +0300 Subject: [PATCH 4/4] fix data partitioning --- .../stl/include/ops_stl.hpp | 1 + .../stl/src/ops_stl.cpp | 64 +++++++++++-------- 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/tasks/perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp b/tasks/perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp index f10468270..12dddf507 100644 --- a/tasks/perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp +++ b/tasks/perepelkin_i_convex_hull_graham_scan/stl/include/ops_stl.hpp @@ -24,6 +24,7 @@ class PerepelkinIConvexHullGrahamScanSTL : public BaseTask { static size_t FindPivotParallel(const std::vector> &pts); static void ParallelSort(std::vector> &data, const std::pair &pivot); + static void DataPartitioning(size_t total_size, const int &threads, std::vector &start); static void HullConstruction(std::vector> &hull, const std::vector> &pts, diff --git a/tasks/perepelkin_i_convex_hull_graham_scan/stl/src/ops_stl.cpp b/tasks/perepelkin_i_convex_hull_graham_scan/stl/src/ops_stl.cpp index 75762f65c..1c8e39fad 100644 --- a/tasks/perepelkin_i_convex_hull_graham_scan/stl/src/ops_stl.cpp +++ b/tasks/perepelkin_i_convex_hull_graham_scan/stl/src/ops_stl.cpp @@ -54,28 +54,25 @@ bool PerepelkinIConvexHullGrahamScanSTL::RunImpl() { } size_t PerepelkinIConvexHullGrahamScanSTL::FindPivotParallel(const std::vector> &pts) { - size_t pivot_idx = 0; - const int threads = ppc::util::GetNumThreads(); - const size_t block_size = pts.size() / threads; + const int threads = std::min(ppc::util::GetNumThreads(), static_cast(pts.size())); - std::vector local_idx(threads, 0); + // Partitioning + std::vector start(threads + 1); + DataPartitioning(pts.size(), threads, start); - // Parallel local pivot finding + // Parallel search + std::vector local_idx(threads, 0); { - std::vector workers; + std::vector workers(threads); for (int tid = 0; tid < threads; tid++) { workers.emplace_back([&, tid]() { - size_t local = pivot_idx; + size_t begin = start[tid]; + size_t end = start[tid + 1]; - size_t start = tid * block_size; - size_t end = (tid + 1) * block_size; + size_t local = begin; - if (start == 0) { - start = 1; - } - - for (size_t i = start; i < end; i++) { + for (size_t i = begin + 1; i < end; i++) { if (pts[i].second < pts[local].second || (pts[i].second == pts[local].second && pts[i].first < pts[local].first)) { local = i; @@ -87,7 +84,9 @@ size_t PerepelkinIConvexHullGrahamScanSTL::FindPivotParallel(const std::vector> &data, const std::pair &pivot) { - const int threads = ppc::util::GetNumThreads(); - const size_t block_size = data.size() / threads; + const int threads = std::min(ppc::util::GetNumThreads(), static_cast(data.size())); + // Partitioning std::vector start(threads + 1); - for (int i = 0; i <= threads; i++) { - start[i] = static_cast(i * block_size); - } + DataPartitioning(data.size(), threads, start); // Parallel local sorting { - std::vector workers; + std::vector workers(threads); for (int tid = 0; tid < threads; tid++) { workers.emplace_back([&, tid]() { @@ -124,7 +121,7 @@ void PerepelkinIConvexHullGrahamScanSTL::ParallelSort(std::vector workers; + std::vector workers(threads); for (int i = 0; i < threads; i += 2 * size) { if (i + size >= threads) { @@ -143,9 +140,26 @@ void PerepelkinIConvexHullGrahamScanSTL::ParallelSort(std::vector> &hull, const std::vector> &pts, - const std::pair &pivot) { +void PerepelkinIConvexHullGrahamScanSTL::DataPartitioning(size_t total_size, const int &threads, + std::vector &start) { + size_t base = total_size / threads; + size_t rem = total_size % threads; + + size_t offset = 0; + + for (int i = 0; i < threads; i++) { + start[i] = static_cast(offset); + + size_t extra = std::cmp_less(i, rem) ? 1 : 0; + offset += base + extra; + } + + start[threads] = static_cast(total_size); +} + +void PerepelkinIConvexHullGrahamScanSTL::HullConstruction(std::vector> &hull, + const std::vector> &pts, + const std::pair &pivot) { hull.reserve(pts.size() + 1); hull.push_back(pivot);