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
16 changes: 16 additions & 0 deletions tasks/vinyaikina_e_quicksort_simple/common/include/common.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <string>
#include <tuple>
#include <vector>

#include "task/include/task.hpp"

namespace vinyaikina_e_quicksort_simple {

using InType = std::vector<int>;
using OutType = std::vector<int>;
using TestType = std::tuple<int, std::string>;
using BaseTask = ppc::task::Task<InType, OutType>;

} // namespace vinyaikina_e_quicksort_simple
9 changes: 9 additions & 0 deletions tasks/vinyaikina_e_quicksort_simple/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"student": {
"first_name": "Екатерина",
"group_number": "3823Б1ПР3",
"last_name": "Виняйкина",
"middle_name": "Александровна",
"task_number": "3"
}
}
26 changes: 26 additions & 0 deletions tasks/vinyaikina_e_quicksort_simple/mpi/include/ops_mpi.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <vector>

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

namespace vinyaikina_e_quicksort_simple {

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

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

std::vector<int> data_;
};

} // namespace vinyaikina_e_quicksort_simple
153 changes: 153 additions & 0 deletions tasks/vinyaikina_e_quicksort_simple/mpi/src/ops_mpi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#include "vinyaikina_e_quicksort_simple/mpi/include/ops_mpi.hpp"

#include <mpi.h>

#include <algorithm>
#include <utility>
#include <vector>

#include "vinyaikina_e_quicksort_simple/common/include/common.hpp"

namespace vinyaikina_e_quicksort_simple {

namespace {

std::pair<int, int> Partition(std::vector<int> &arr, int lo, int hi) {
int pivot = arr[lo + ((hi - lo) / 2)];
int i = lo;
int j = hi;
while (i <= j) {
while (arr[i] < pivot) {
i++;
}
while (arr[j] > pivot) {
j--;
}
if (i <= j) {
std::swap(arr[i], arr[j]);
i++;
j--;
}
}
return {i, j};
}

void QuickSort(std::vector<int> &arr, int left, int right) {
std::vector<std::pair<int, int>> stack;
stack.emplace_back(left, right);
while (!stack.empty()) {
auto [lo, hi] = stack.back();
stack.pop_back();
if (lo >= hi) {
continue;
}
auto [i, j] = Partition(arr, lo, hi);
if (lo < j) {
stack.emplace_back(lo, j);
}
if (i < hi) {
stack.emplace_back(i, hi);
}
}
}

std::vector<int> MergeSorted(const std::vector<int> &a, const std::vector<int> &b) {
std::vector<int> result;
result.reserve(a.size() + b.size());
int i = 0;
int j = 0;
int a_size = static_cast<int>(a.size());
int b_size = static_cast<int>(b.size());
while (i < a_size && j < b_size) {
if (a[i] <= b[j]) {
result.push_back(a[i]);
i++;
} else {
result.push_back(b[j]);
j++;
}
}
while (i < a_size) {
result.push_back(a[i]);
i++;
}
while (j < b_size) {
result.push_back(b[j]);
j++;
}
return result;
}

} // namespace

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

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

bool VinyaikinaEQuicksortSimpleMPI::PreProcessingImpl() {
data_ = GetInput();
return true;
}

bool VinyaikinaEQuicksortSimpleMPI::RunImpl() {
int rank = 0;
int proc_count = 0;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &proc_count);

int n = static_cast<int>(data_.size());
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

if (n == 0) {
return true;
}

std::vector<int> send_counts(proc_count);
std::vector<int> offsets(proc_count);
int base_chunk = n / proc_count;
int extra = n % proc_count;
for (int i = 0; i < proc_count; i++) {
send_counts[i] = base_chunk + (i < extra ? 1 : 0);
offsets[i] = (i > 0) ? (offsets[i - 1] + send_counts[i - 1]) : 0;
}

std::vector<int> local_data(send_counts[rank]);
MPI_Scatterv(data_.data(), send_counts.data(), offsets.data(), MPI_INT, local_data.data(), send_counts[rank], MPI_INT,
0, MPI_COMM_WORLD);

if (local_data.size() > 1) {
QuickSort(local_data, 0, static_cast<int>(local_data.size()) - 1);
}

std::vector<int> gathered;
if (rank == 0) {
gathered.resize(n);
}
MPI_Gatherv(local_data.data(), send_counts[rank], MPI_INT, gathered.data(), send_counts.data(), offsets.data(),
MPI_INT, 0, MPI_COMM_WORLD);

if (rank == 0) {
std::vector<int> merged(gathered.begin(), gathered.begin() + send_counts[0]);
for (int i = 1; i < proc_count; i++) {
std::vector<int> chunk(gathered.begin() + offsets[i], gathered.begin() + offsets[i] + send_counts[i]);
merged = MergeSorted(merged, chunk);
}
data_ = std::move(merged);
}

MPI_Bcast(data_.data(), n, MPI_INT, 0, MPI_COMM_WORLD);

return true;
}

bool VinyaikinaEQuicksortSimpleMPI::PostProcessingImpl() {
GetOutput() = data_;
return true;
}

} // namespace vinyaikina_e_quicksort_simple
Loading
Loading