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

#include <algorithm>
#include <cstddef>
#include <string>
#include <tuple>
#include <vector>

#include "task/include/task.hpp"

namespace goriacheva_k_strassen_algorithm {

using Matrix = std::vector<std::vector<double>>;

struct InType {
Matrix a;
Matrix b;
};

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

inline std::vector<double> Flatten(const Matrix &m) {
std::vector<double> buf;
buf.reserve(m.size() * m.size());
for (const auto &row : m) {
buf.insert(buf.end(), row.begin(), row.end());
}
return buf;
}

inline Matrix UnFlatten(const std::vector<double> &buf, std::size_t n) {
Matrix m(n, std::vector<double>(n));
for (std::size_t i = 0; i < n; ++i) {
for (std::size_t j = 0; j < n; ++j) {
m[i][j] = buf[(i * n) + j];
}
}
return m;
}

inline bool IsSquare(const Matrix &m) {
if (m.empty()) {
return false;
}
const std::size_t n = m.size();
return std::ranges::all_of(m, [n](const auto &r) { return r.size() == n; });
}

inline std::size_t NextPowerOfTwo(std::size_t n) {
std::size_t p = 1;
while (p < n) {
p <<= 1;
}
return p;
}

inline Matrix PadMatrix(const Matrix &a, std::size_t new_size) {
Matrix r(new_size, std::vector<double>(new_size, 0.0));
for (std::size_t i = 0; i < a.size(); ++i) {
for (std::size_t j = 0; j < a.size(); ++j) {
r[i][j] = a[i][j];
}
}
return r;
}

inline Matrix CropMatrix(const Matrix &a, std::size_t size) {
Matrix r(size, std::vector<double>(size));
for (std::size_t i = 0; i < size; ++i) {
for (std::size_t j = 0; j < size; ++j) {
r[i][j] = a[i][j];
}
}
return r;
}

inline Matrix Add(const Matrix &a, const Matrix &b) {
std::size_t n = a.size();
Matrix c(n, std::vector<double>(n));
for (std::size_t i = 0; i < n; ++i) {
for (std::size_t j = 0; j < n; ++j) {
c[i][j] = a[i][j] + b[i][j];
}
}
return c;
}

inline Matrix Sub(const Matrix &a, const Matrix &b) {
std::size_t n = a.size();
Matrix c(n, std::vector<double>(n));
for (std::size_t i = 0; i < n; ++i) {
for (std::size_t j = 0; j < n; ++j) {
c[i][j] = a[i][j] - b[i][j];
}
}
return c;
}

inline Matrix NaiveMultiply(const Matrix &a, const Matrix &b) {
std::size_t n = a.size();
Matrix c(n, std::vector<double>(n, 0.0));
for (std::size_t i = 0; i < n; ++i) {
for (std::size_t k = 0; k < n; ++k) {
for (std::size_t j = 0; j < n; ++j) {
c[i][j] += a[i][k] * b[k][j];
}
}
}
return c;
}

inline Matrix Strassen(const Matrix &a, const Matrix &b, std::size_t threshold = 128) // NOLINT(misc-no-recursion)
{
std::size_t n = a.size();
if (n <= threshold) {
return NaiveMultiply(a, b);
}

std::size_t k = n / 2;

Matrix a11(k, std::vector<double>(k));
Matrix a12(k, std::vector<double>(k));
Matrix a21(k, std::vector<double>(k));
Matrix a22(k, std::vector<double>(k));
Matrix b11(k, std::vector<double>(k));
Matrix b12(k, std::vector<double>(k));
Matrix b21(k, std::vector<double>(k));
Matrix b22(k, std::vector<double>(k));

for (std::size_t i = 0; i < k; ++i) {
for (std::size_t j = 0; j < k; ++j) {
a11[i][j] = a[i][j];
a12[i][j] = a[i][j + k];
a21[i][j] = a[i + k][j];
a22[i][j] = a[i + k][j + k];
b11[i][j] = b[i][j];
b12[i][j] = b[i][j + k];
b21[i][j] = b[i + k][j];
b22[i][j] = b[i + k][j + k];
}
}

Matrix m1 = Strassen(Add(a11, a22), Add(b11, b22), threshold);
Matrix m2 = Strassen(Add(a21, a22), b11, threshold);
Matrix m3 = Strassen(a11, Sub(b12, b22), threshold);
Matrix m4 = Strassen(a22, Sub(b21, b11), threshold);
Matrix m5 = Strassen(Add(a11, a12), b22, threshold);
Matrix m6 = Strassen(Sub(a21, a11), Add(b11, b12), threshold);
Matrix m7 = Strassen(Sub(a12, a22), Add(b21, b22), threshold);

Matrix c(n, std::vector<double>(n));
for (std::size_t i = 0; i < k; ++i) {
for (std::size_t j = 0; j < k; ++j) {
c[i][j] = m1[i][j] + m4[i][j] - m5[i][j] + m7[i][j];
c[i][j + k] = m3[i][j] + m5[i][j];
c[i + k][j] = m2[i][j] + m4[i][j];
c[i + k][j + k] = m1[i][j] - m2[i][j] + m3[i][j] + m6[i][j];
}
}

return c;
}

} // namespace goriacheva_k_strassen_algorithm
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 72 additions & 0 deletions tasks/goriacheva_k_strassen_algorithm/data/tests.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
[
{ "name": "1x1_single", "input": { "A": [[7.0]], "B": [[3.0]] }, "result": [[21.0]] },
{ "name": "2x2_simple", "input": { "A": [[1.0,2.0],[3.0,4.0]], "B": [[5.0,6.0],[7.0,8.0]] }, "result": [[19.0,22.0],[43.0,50.0]] },
{ "name": "2x2_zeros", "input": { "A": [[0.0,0.0],[0.0,0.0]], "B": [[1.0,2.0],[3.0,4.0]] }, "result": [[0.0,0.0],[0.0,0.0]] },
{ "name": "2x2_identity", "input": { "A": [[1.0,0.0],[0.0,1.0]], "B": [[2.0,3.0],[4.0,5.0]] }, "result": [[2.0,3.0],[4.0,5.0]] },
{ "name": "3x3_random", "input": { "A": [[1.0,2.0,3.0],[4.0,5.0,6.0],[7.0,8.0,9.0]], "B": [[9.0,8.0,7.0],[6.0,5.0,4.0],[3.0,2.0,1.0]] }, "result": [[30.0,24.0,18.0],[84.0,69.0,54.0],[138.0,114.0,90.0]] },
{ "name": "3x3_identity", "input": { "A": [[1.0,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,1.0]], "B": [[3.0,2.0,1.0],[6.0,5.0,4.0],[9.0,8.0,7.0]] }, "result": [[3.0,2.0,1.0],[6.0,5.0,4.0],[9.0,8.0,7.0]] },
{ "name": "3x3_diagonal", "input": { "A": [[1.0,0.0,0.0],[0.0,2.0,0.0],[0.0,0.0,3.0]], "B": [[4.0,0.0,0.0],[0.0,5.0,0.0],[0.0,0.0,6.0]] }, "result": [[4.0,0.0,0.0],[0.0,10.0,0.0],[0.0,0.0,18.0]] },
{ "name": "2x2_negatives", "input": { "A": [[-1.0,2.0],[3.0,-4.0]], "B": [[5.0,-6.0],[-7.0,8.0]] }, "result": [[-19.0,22.0],[43.0,-50.0]] },
{ "name": "3x3_repeats", "input": { "A": [[2.0,2.0,2.0],[2.0,2.0,2.0],[2.0,2.0,2.0]], "B": [[1.0,2.0,3.0],[1.0,2.0,3.0],[1.0,2.0,3.0]] }, "result": [[6.0,12.0,18.0],[6.0,12.0,18.0],[6.0,12.0,18.0]] },
{ "name": "3x3_fractional", "input": { "A": [[1.5,2.0,3.5],[4.0,5.0,6.5],[7.5,8.0,9.5]], "B": [[0.5,1.0,1.5],[2.0,2.5,3.0],[3.5,4.0,4.5]] }, "result": [[17.0,20.5,24.0],[34.75,42.5,50.25],[53.0,65.5,78.0]] },
{ "name": "4x4_simple", "input": { "A": [[1.0,2.0,3.0,4.0],[5.0,6.0,7.0,8.0],[9.0,10.0,11.0,12.0],[13.0,14.0,15.0,16.0]], "B": [[16.0,15.0,14.0,13.0],[12.0,11.0,10.0,9.0],[8.0,7.0,6.0,5.0],[4.0,3.0,2.0,1.0]] }, "result": [[80.0,70.0,60.0,50.0],[240.0,214.0,188.0,162.0],[400.0,358.0,316.0,274.0],[560.0,502.0,444.0,386.0]] },
{ "name": "4x4_identity", "input": { "A": [[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[0.0,0.0,0.0,1.0]], "B": [[1.0,2.0,3.0,4.0],[5.0,6.0,7.0,8.0],[9.0,10.0,11.0,12.0],[13.0,14.0,15.0,16.0]] }, "result": [[1.0,2.0,3.0,4.0],[5.0,6.0,7.0,8.0],[9.0,10.0,11.0,12.0],[13.0,14.0,15.0,16.0]] },
{ "name": "4x4_negatives", "input": { "A": [[-1.0,2.0,-3.0,4.0],[5.0,-6.0,7.0,-8.0],[-9.0,10.0,-11.0,12.0],[13.0,-14.0,15.0,-16.0]], "B": [[16.0,-15.0,14.0,-13.0],[-12.0,11.0,-10.0,9.0],[8.0,-7.0,6.0,-5.0],[-4.0,3.0,-2.0,1.0]] }, "result": [[-80.0,70.0,-60.0,50.0],[240.0,-214.0,188.0,-162.0],[-400.0,358.0,-316.0,274.0],[560.0,-502.0,444.0,-386.0]] },
{ "name": "4x4_repeats", "input": { "A": [[1.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0]], "B": [[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0]] }, "result": [[8.0,8.0,8.0,8.0],[8.0,8.0,8.0,8.0],[8.0,8.0,8.0,8.0],[8.0,8.0,8.0,8.0]] },
{ "name": "4x4_fractional", "input": { "A": [[1.5, 2.0, 3.0, 4.5],[5.5, 6.5, 7.0, 8.0],[9.0, 10.5, 11.5, 12.0],[13.0, 14.5, 15.0, 16.5]], "B": [[0.5, 1.0, 1.5, 2.0],[2.5, 3.0, 3.5, 4.0],[4.5, 5.0, 5.5, 6.0],[6.5, 7.0, 7.5, 8.0]] }, "result": [[48.5, 54.0, 59.5, 65.0],[102.5, 116.0, 129.5, 143.0],[160.5, 182.0, 203.5, 225.0],[217.5, 247.0, 276.5, 306.0]] },
{ "name": "5x5_identity", "input": { "A": [[1.0,0.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0,0.0],[0.0,0.0,1.0,0.0,0.0],[0.0,0.0,0.0,1.0,0.0],[0.0,0.0,0.0,0.0,1.0]], "B": [[1.0,2.0,3.0,4.0,5.0],[6.0,7.0,8.0,9.0,10.0],[11.0,12.0,13.0,14.0,15.0],[16.0,17.0,18.0,19.0,20.0],[21.0,22.0,23.0,24.0,25.0]] }, "result": [[1.0,2.0,3.0,4.0,5.0],[6.0,7.0,8.0,9.0,10.0],[11.0,12.0,13.0,14.0,15.0],[16.0,17.0,18.0,19.0,20.0],[21.0,22.0,23.0,24.0,25.0]] },
{
"name": "6x6_identity",
"input": {
"A": [[1,0,0,0,0,0],
[0,1,0,0,0,0],
[0,0,1,0,0,0],
[0,0,0,1,0,0],
[0,0,0,0,1,0],
[0,0,0,0,0,1]],
"B": [[1,2,3,4,5,6],
[7,8,9,10,11,12],
[13,14,15,16,17,18],
[19,20,21,22,23,24],
[25,26,27,28,29,30],
[31,32,33,34,35,36]]
},
"result": [[1,2,3,4,5,6],
[7,8,9,10,11,12],
[13,14,15,16,17,18],
[19,20,21,22,23,24],
[25,26,27,28,29,30],
[31,32,33,34,35,36]]
},
{
"name": "8x8_mixed",
"input": {
"A": [[1,2,3,4,5,6,7,8],
[8,7,6,5,4,3,2,1],
[1,3,5,7,9,11,13,15],
[2,4,6,8,10,12,14,16],
[1,1,1,1,1,1,1,1],
[2,2,2,2,2,2,2,2],
[3,3,3,3,3,3,3,3],
[4,4,4,4,4,4,4,4]],
"B": [[1,0,0,0,0,0,0,0],
[0,1,0,0,0,0,0,0],
[0,0,1,0,0,0,0,0],
[0,0,0,1,0,0,0,0],
[0,0,0,0,1,0,0,0],
[0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,1,0],
[0,0,0,0,0,0,0,1]]
},
"result": [[1,2,3,4,5,6,7,8],
[8,7,6,5,4,3,2,1],
[1,3,5,7,9,11,13,15],
[2,4,6,8,10,12,14,16],
[1,1,1,1,1,1,1,1],
[2,2,2,2,2,2,2,2],
[3,3,3,3,3,3,3,3],
[4,4,4,4,4,4,4,4]]
}


]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions tasks/goriacheva_k_strassen_algorithm/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"student": {
"first_name": "Ксения",
"last_name": "Горячева",
"middle_name": "Александровна",
"group_number": "3823Б1ФИ2",
"task_number": "3"
}
}
28 changes: 28 additions & 0 deletions tasks/goriacheva_k_strassen_algorithm/mpi/include/ops_mpi.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

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

namespace goriacheva_k_strassen_algorithm {

class GoriachevaKStrassenAlgorithmMPI : public BaseTask {
public:
static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() {
return ppc::task::TypeOfTask::kMPI;
}

explicit GoriachevaKStrassenAlgorithmMPI(const InType &in);

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

InType input_matrices_;
OutType result_matrix_;

static Matrix MpiStrassenTop(const Matrix &a, const Matrix &b);
};

} // namespace goriacheva_k_strassen_algorithm
Loading
Loading