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

#include <string>
#include <tuple>

#include "task/include/task.hpp"

namespace vinyaikina_e_vert_ribbon_scheme {

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

} // namespace vinyaikina_e_vert_ribbon_scheme
9 changes: 9 additions & 0 deletions tasks/vinyaikina_e_vert_ribbon_scheme/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": "2"
}
}
30 changes: 30 additions & 0 deletions tasks/vinyaikina_e_vert_ribbon_scheme/mpi/include/ops_mpi.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 "vinyaikina_e_vert_ribbon_scheme/common/include/common.hpp"

namespace vinyaikina_e_vert_ribbon_scheme {

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

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

int rows_ = 0;
int cols_ = 0;
std::vector<int> matrix_;
std::vector<int> vector_;
std::vector<int> result_;
};

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

#include <mpi.h>

#include <cstddef>
#include <vector>

#include "vinyaikina_e_vert_ribbon_scheme/common/include/common.hpp"

namespace vinyaikina_e_vert_ribbon_scheme {

namespace {

void ComputeColumnDistribution(int cols, int num_proc, std::vector<int> &counts, std::vector<int> &starts) {
int base = cols / num_proc;
int rem = cols % num_proc;
for (int i = 0; i < num_proc; i++) {
counts[i] = base + (i < rem ? 1 : 0);
}
starts[0] = 0;
for (int i = 1; i < num_proc; i++) {
starts[i] = starts[i - 1] + counts[i - 1];
}
}

std::vector<int> PackMatrixBuffer(int rows, int cols, int num_proc, const std::vector<int> &matrix,
const std::vector<int> &col_counts, const std::vector<int> &col_starts,
std::vector<int> &send_counts, std::vector<int> &send_offsets) {
int total_send = 0;
for (int pr = 0; pr < num_proc; pr++) {
send_counts[pr] = rows * col_counts[pr];
send_offsets[pr] = total_send;
total_send += send_counts[pr];
}
std::vector<int> buf(total_send);
for (int pr = 0; pr < num_proc; pr++) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < col_counts[pr]; j++) {
buf[send_offsets[pr] + (i * col_counts[pr]) + j] = matrix[(i * cols) + col_starts[pr] + j];
}
}
}
return buf;
}

} // namespace

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

bool VinyaikinaEVertRibbonSchemeMPI::ValidationImpl() {
return GetInput() > 0 && GetOutput() == 0;
}

bool VinyaikinaEVertRibbonSchemeMPI::PreProcessingImpl() {
rows_ = GetInput();
cols_ = GetInput();
if (rows_ <= 0 || cols_ <= 0) {
return false;
}
int rank = 0;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
matrix_.assign(static_cast<std::size_t>(rows_) * cols_, 1);
vector_.assign(cols_, 1);
}
result_.assign(rows_, 0);
return true;
}

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

std::vector<int> col_counts(size);
std::vector<int> col_starts(size);
ComputeColumnDistribution(cols_, size, col_counts, col_starts);

int my_cols = col_counts[rank];

std::vector<int> matrix_send_buf;
std::vector<int> matrix_send_counts(size, 0);
std::vector<int> matrix_send_offsets(size, 0);

if (rank == 0) {
matrix_send_buf =
PackMatrixBuffer(rows_, cols_, size, matrix_, col_counts, col_starts, matrix_send_counts, matrix_send_offsets);
}

int matrix_recv_count = rows_ * my_cols;
std::vector<int> local_matrix(matrix_recv_count);
MPI_Scatterv(matrix_send_buf.data(), matrix_send_counts.data(), matrix_send_offsets.data(), MPI_INT,
local_matrix.data(), matrix_recv_count, MPI_INT, 0, MPI_COMM_WORLD);

std::vector<int> vector_send_counts(size, 0);
std::vector<int> vector_send_offsets(size, 0);
for (int pr = 0; pr < size; pr++) {
vector_send_counts[pr] = col_counts[pr];
vector_send_offsets[pr] = col_starts[pr];
}

std::vector<int> local_vector(my_cols);
MPI_Scatterv(vector_.data(), vector_send_counts.data(), vector_send_offsets.data(), MPI_INT, local_vector.data(),
my_cols, MPI_INT, 0, MPI_COMM_WORLD);

std::vector<int> local_result(rows_, 0);
for (int i = 0; i < rows_; i++) {
for (int j = 0; j < my_cols; j++) {
local_result[i] += local_matrix[(i * my_cols) + j] * local_vector[j];
}
}

result_.assign(rows_, 0);
MPI_Reduce(local_result.data(), result_.data(), rows_, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);

int total = 0;
if (rank == 0) {
for (int i = 0; i < rows_; i++) {
total += result_[i];
}
for (int dest = 1; dest < size; dest++) {
MPI_Send(&total, 1, MPI_INT, dest, 0, MPI_COMM_WORLD);
}
} else {
MPI_Recv(&total, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}

GetOutput() = total;
return true;
}

bool VinyaikinaEVertRibbonSchemeMPI::PostProcessingImpl() {
if (GetInput() == 0) {
return false;
}
GetOutput() /= GetInput();
return true;
}

} // namespace vinyaikina_e_vert_ribbon_scheme
Loading
Loading