Skip to content
Merged
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
22 changes: 22 additions & 0 deletions tasks/makovskiy_i_graham_hull/omp/include/ops_omp.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

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

namespace makovskiy_i_graham_hull {

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

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

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

#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <vector>

#include "makovskiy_i_graham_hull/common/include/common.hpp"

namespace makovskiy_i_graham_hull {

namespace {

double CrossProduct(const Point &o, const Point &a, const Point &b) {
return ((a.x - o.x) * (b.y - o.y)) - ((a.y - o.y) * (b.x - o.x));
}

double DistSq(const Point &a, const Point &b) {
return ((a.x - b.x) * (a.x - b.x)) + ((a.y - b.y) * (a.y - b.y));
}

size_t FindMinPointIndexOMP(const std::vector<Point> &points) {
size_t min_idx = 0;
size_t n = points.size();
#pragma omp parallel default(none) shared(points, n, min_idx)
{
size_t local_min = 0;
#pragma omp for
for (size_t i = 1; i < n; ++i) {
if (points[i].y < points[local_min].y - 1e-9 ||
(std::abs(points[i].y - points[local_min].y) <= 1e-9 && points[i].x < points[local_min].x)) {
local_min = i;
}
}
#pragma omp critical
{
if (points[local_min].y < points[min_idx].y - 1e-9 ||
(std::abs(points[local_min].y - points[min_idx].y) <= 1e-9 && points[local_min].x < points[min_idx].x)) {
min_idx = local_min;
}
}
}
return min_idx;
}

template <typename RandomIt, typename Compare>
void OmpQuickSort(RandomIt first, RandomIt last, Compare comp) {
if (last - first < 2048) {
std::sort(first, last, comp);
return;
}
auto pivot = *(first + ((last - first) / 2));
RandomIt middle1 = std::partition(first, last, [pivot, comp](const auto &a) { return comp(a, pivot); });
RandomIt middle2 = std::partition(middle1, last, [pivot, comp](const auto &a) { return !comp(pivot, a); });

#pragma omp task default(none) firstprivate(first, middle1, comp)
OmpQuickSort(first, middle1, comp);

#pragma omp task default(none) firstprivate(middle2, last, comp)
OmpQuickSort(middle2, last, comp);

#pragma omp taskwait
}

std::vector<Point> FilterPointsOMP(const std::vector<Point> &points, const Point &p0) {
size_t n = points.size();
std::vector<uint8_t> keep(n, 1);

#pragma omp parallel for default(none) shared(n, points, keep, p0)
for (size_t i = 1; i < n - 1; ++i) {
if (std::abs(CrossProduct(p0, points[i], points[i + 1])) < 1e-9) {
keep[i] = 0;
}
}

std::vector<Point> filtered;
filtered.reserve(n);
for (size_t i = 0; i < n; ++i) {
if (keep[i] != 0) {
filtered.push_back(points[i]);
}
}
return filtered;
}

std::vector<Point> BuildHull(const std::vector<Point> &filtered) {
std::vector<Point> hull;
hull.push_back(filtered[0]);
hull.push_back(filtered[1]);
hull.push_back(filtered[2]);

for (size_t i = 3; i < filtered.size(); ++i) {
while (hull.size() > 1 && CrossProduct(hull[hull.size() - 2], hull.back(), filtered[i]) <= 1e-9) {
hull.pop_back();
}
hull.push_back(filtered[i]);
}
return hull;
}

} // namespace

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

bool ConvexHullGrahamOMP::ValidationImpl() {
return true;
}

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

bool ConvexHullGrahamOMP::RunImpl() {
InType points = GetInput();
if (points.size() < 3) {
GetOutput() = points;
return true;
}

size_t min_idx = FindMinPointIndexOMP(points);

std::swap(points[0], points[min_idx]);
Point p0 = points[0];

auto comp = [p0](const Point &a, const Point &b) {
double cp = CrossProduct(p0, a, b);
if (std::abs(cp) < 1e-9) {
return DistSq(p0, a) < DistSq(p0, b);
}
return cp > 0;
};

#pragma omp parallel default(none) shared(points, comp)
{
#pragma omp single nowait
OmpQuickSort(points.begin() + 1, points.end(), comp);
}

InType filtered = FilterPointsOMP(points, p0);

if (filtered.size() < 3) {
GetOutput() = filtered;
return true;
}

GetOutput() = BuildHull(filtered);
return true;
}

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

} // namespace makovskiy_i_graham_hull
1 change: 1 addition & 0 deletions tasks/makovskiy_i_graham_hull/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"tasks": {
"all": "enabled",
"omp": "enabled",
"seq": "enabled"
},
"tasks_type": "threads"
Expand Down
20 changes: 17 additions & 3 deletions tasks/makovskiy_i_graham_hull/tests/functional/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <tuple>

#include "makovskiy_i_graham_hull/common/include/common.hpp"
#include "makovskiy_i_graham_hull/omp/include/ops_omp.hpp"
#include "makovskiy_i_graham_hull/seq/include/ops_seq.hpp"
#include "util/include/func_test_util.hpp"
#include "util/include/util.hpp"
Expand Down Expand Up @@ -39,6 +40,14 @@ class MakovskiyIGrahamHullRunFuncTestsThreads : public ppc::util::BaseRunFuncTes
input_data_ = {{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}};
} else if (test_id == 8) {
input_data_ = {{-2, -2}, {2, -2}, {2, 2}, {-2, 2}, {0, 0}};
} else if (test_id == 9) {
input_data_.clear();
input_data_.reserve(3300);
for (int i = 0; i < 60; ++i) {
for (int j = 0; j < 55; ++j) {
input_data_.push_back({static_cast<double>(i), static_cast<double>(j)});
}
}
}
}

Expand Down Expand Up @@ -69,6 +78,9 @@ class MakovskiyIGrahamHullRunFuncTestsThreads : public ppc::util::BaseRunFuncTes
if (test_id == 8) {
return output_data.size() == 4;
}
if (test_id == 9) {
return output_data.size() == 4;
}

return false;
}
Expand All @@ -87,17 +99,19 @@ TEST_P(MakovskiyIGrahamHullRunFuncTestsThreads, GrahamHullTests) {
ExecuteTest(GetParam());
}

const std::array<TestType, 8> kTestParam = {std::make_tuple(1, "square_with_internal_point"),
const std::array<TestType, 9> kTestParam = {std::make_tuple(1, "square_with_internal_point"),
std::make_tuple(2, "triangle"),
std::make_tuple(3, "collinear_points_on_edges"),
std::make_tuple(4, "empty_array"),
std::make_tuple(5, "two_points"),
std::make_tuple(6, "diagonal_line"),
std::make_tuple(7, "vertical_line"),
std::make_tuple(8, "negative_coordinates")};
std::make_tuple(8, "negative_coordinates"),
std::make_tuple(9, "large_grid_for_quicksort")};

const auto kTestTasksList = std::tuple_cat(
ppc::util::AddFuncTask<ConvexHullGrahamSEQ, InType>(kTestParam, PPC_SETTINGS_makovskiy_i_graham_hull));
ppc::util::AddFuncTask<ConvexHullGrahamSEQ, InType>(kTestParam, PPC_SETTINGS_makovskiy_i_graham_hull),
ppc::util::AddFuncTask<ConvexHullGrahamOMP, InType>(kTestParam, PPC_SETTINGS_makovskiy_i_graham_hull));

const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList);

Expand Down
3 changes: 2 additions & 1 deletion tasks/makovskiy_i_graham_hull/tests/performance/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <cmath>

#include "makovskiy_i_graham_hull/common/include/common.hpp"
#include "makovskiy_i_graham_hull/omp/include/ops_omp.hpp"
#include "makovskiy_i_graham_hull/seq/include/ops_seq.hpp"
#include "util/include/perf_test_util.hpp"

Expand Down Expand Up @@ -38,7 +39,7 @@ TEST_P(MakovskiyIGrahamHullRunPerfTestsThreads, RunPerfModes) {
namespace {

const auto kAllPerfTasks =
ppc::util::MakeAllPerfTasks<InType, ConvexHullGrahamSEQ>(PPC_SETTINGS_makovskiy_i_graham_hull);
ppc::util::MakeAllPerfTasks<InType, ConvexHullGrahamSEQ, ConvexHullGrahamOMP>(PPC_SETTINGS_makovskiy_i_graham_hull);

const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks);

Expand Down
Loading