From 15791914e90edb6dafcaf274943e43e920b7bd82 Mon Sep 17 00:00:00 2001 From: WickedJack99 Date: Mon, 16 Jun 2025 19:38:13 +0200 Subject: [PATCH] hallo layers --- .vscode/settings.json | 14 ++- lab11/game_of_life/game_of_life.cpp | 1 + lab11/game_of_life/makefile | 3 +- lab11/game_of_life/super_grid.cpp | 159 ++++++++++++++++++++++++++++ lab11/game_of_life/super_grid.h | 157 +++++++++++++++++++-------- lab11/game_of_life/test.cpp | 80 ++++++++++---- 6 files changed, 347 insertions(+), 67 deletions(-) create mode 100644 lab11/game_of_life/super_grid.cpp diff --git a/.vscode/settings.json b/.vscode/settings.json index 2d73094..566546b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -68,6 +68,18 @@ "set": "cpp", "unordered_map": "cpp", "xhash": "cpp", - "xtree": "cpp" + "xtree": "cpp", + "codecvt": "cpp", + "condition_variable": "cpp", + "cstdarg": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "map": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "string_view": "cpp", + "numbers": "cpp", + "semaphore": "cpp", + "cinttypes": "cpp" } } \ No newline at end of file diff --git a/lab11/game_of_life/game_of_life.cpp b/lab11/game_of_life/game_of_life.cpp index 6c6ca21..672f843 100644 --- a/lab11/game_of_life/game_of_life.cpp +++ b/lab11/game_of_life/game_of_life.cpp @@ -7,6 +7,7 @@ void GameOfLife::step() { SuperGrid next = SuperGrid::zeros(grid_.rows(), grid_.cols(), grid_.get_communicator()); const int rows = grid_.rows(); const int cols = grid_.cols(); + grid_.update(); for (int i = 0; i < rows; ++i) { for (int j = 0; j < cols; ++j) { const int numLiveNeighbors = countLiveNeighbors(i, j); diff --git a/lab11/game_of_life/makefile b/lab11/game_of_life/makefile index 7eed0f4..113a581 100644 --- a/lab11/game_of_life/makefile +++ b/lab11/game_of_life/makefile @@ -2,7 +2,8 @@ PROGRAM_NAME = game_of_life SOURCE_FILES = game_of_life.cpp \ utils.cpp \ patterns.cpp \ - matrix_io.cpp + matrix_io.cpp \ + super_grid.cpp COMPILER_FLAGS = -std=c++17 -Wall -Wextra -Wall -Werror \ -Wno-sign-compare \ diff --git a/lab11/game_of_life/super_grid.cpp b/lab11/game_of_life/super_grid.cpp new file mode 100644 index 0000000..ae0d006 --- /dev/null +++ b/lab11/game_of_life/super_grid.cpp @@ -0,0 +1,159 @@ +#include +#include "super_grid.h" + +std::vector SuperGrid::receive_halos(HaloLayers halo_layers) +{ + std::vector recv_requests(8); + std::cout << halo_layers.top_row.size() << std::endl; + MPI_Irecv(halo_layers.top_row.data(), halo_layers.top_row.size(), MPI_DOUBLE, neighbors_.top, neighbors_.top, comm_, &recv_requests[0]); + MPI_Irecv(halo_layers.right_row.data(), halo_layers.right_row.size(), MPI_DOUBLE, neighbors_.right, neighbors_.right, comm_, &recv_requests[1]); + MPI_Irecv(halo_layers.bottom_row.data(), halo_layers.bottom_row.size(), MPI_DOUBLE, neighbors_.bottom, neighbors_.bottom, comm_, &recv_requests[2]); + MPI_Irecv(halo_layers.left_row.data(), halo_layers.left_row.size(), MPI_DOUBLE, neighbors_.left, neighbors_.left, comm_, &recv_requests[3]); + + MPI_Irecv(&halo_layers.top_right_corner, 1, MPI_DOUBLE, neighbors_.top_right, neighbors_.top_right, comm_, &recv_requests[4]); + MPI_Irecv(&halo_layers.bottom_right_corner, 1, MPI_DOUBLE, neighbors_.bottom_right, neighbors_.bottom_right, comm_, &recv_requests[5]); + MPI_Irecv(&halo_layers.top_left_corner, 1, MPI_DOUBLE, neighbors_.top_left, neighbors_.top_left, comm_, &recv_requests[6]); + MPI_Irecv(&halo_layers.bottom_left_corner, 1, MPI_DOUBLE, neighbors_.bottom_left, neighbors_.bottom_left, comm_, &recv_requests[7]); + + return recv_requests; +} + +std::vector SuperGrid::get_top_row() +{ + std::vector row(cols()); + for (int j = 0; j < cols(); ++j) + row[j] = (*this)(j, 0); + return row; +} + +std::vector SuperGrid::get_bottom_row() +{ + std::vector row(cols()); + for (int j = 0; j < cols(); ++j) + row[j] = (*this)(j, rows() - 1); + return row; +} + +std::vector SuperGrid::get_left_row() +{ + std::vector col(rows()); + for (int i = 0; i < rows(); ++i) + col[i] = (*this)(0, i); + return col; +} + +std::vector SuperGrid::get_right_row() +{ + std::vector col(rows()); + for (int i = 0; i < rows(); ++i) + col[i] = (*this)(cols() - 1, i); + return col; +} + +double SuperGrid::get_top_left_corner() +{ + return (*this)(0, 0); +} + +double SuperGrid::get_top_right_corner() +{ + return (*this)(cols() - 1, 0); +} + +double SuperGrid::get_bottom_left_corner() +{ + return (*this)(0, rows() - 1); +} + +double SuperGrid::get_bottom_right_corner() +{ + return (*this)(cols() - 1, rows() - 1); +} + +std::vector SuperGrid::inform_neighbors() +{ + std::vector top_row = get_top_row(); + std::vector right_row = get_right_row(); + std::vector bottom_row = get_bottom_row(); + std::vector left_row = get_left_row(); + + double top_right_corner = get_top_right_corner(); + double bottom_right_corner = get_bottom_right_corner(); + double top_left_corner = get_top_left_corner(); + double bottom_left_corner = get_bottom_left_corner(); + + if (rank_ == 0) + { + std::cout << "Rank " << rank_ << " neighbors:" << std::endl; + std::cout << " Top: " << neighbors_.top << std::endl; + std::cout << " Right: " << neighbors_.right << std::endl; + std::cout << " Bottom: " << neighbors_.bottom << std::endl; + std::cout << " Left: " << neighbors_.left << std::endl; + std::cout << " Top-Right: " << neighbors_.top_right << std::endl; + std::cout << " Bottom-Right: " << neighbors_.bottom_right << std::endl; + std::cout << " Top-Left: " << neighbors_.top_left << std::endl; + std::cout << " Bottom-Left: " << neighbors_.bottom_left << std::endl; + } + + std::vector send_requests(8); + std::cout << top_row.size() << "inform_neighbors" << std::endl; + MPI_Isend(top_row.data(), top_row.size(), MPI_DOUBLE, neighbors_.top, rank_, comm_, &send_requests[0]); + MPI_Isend(right_row.data(), right_row.size(), MPI_DOUBLE, neighbors_.right, rank_, comm_, &send_requests[1]); + MPI_Isend(bottom_row.data(), bottom_row.size(), MPI_DOUBLE, neighbors_.bottom, rank_, comm_, &send_requests[2]); + MPI_Isend(left_row.data(), left_row.size(), MPI_DOUBLE, neighbors_.left, rank_, comm_, &send_requests[3]); + + MPI_Isend(&top_right_corner, 1, MPI_DOUBLE, neighbors_.top_right, rank_, comm_, &send_requests[4]); + MPI_Isend(&bottom_right_corner, 1, MPI_DOUBLE, neighbors_.bottom_right, rank_, comm_, &send_requests[5]); + MPI_Isend(&top_left_corner, 1, MPI_DOUBLE, neighbors_.top_left, rank_, comm_, &send_requests[6]); + MPI_Isend(&bottom_left_corner, 1, MPI_DOUBLE, neighbors_.bottom_left, rank_, comm_, &send_requests[7]); + + return send_requests; +} + +void SuperGrid::update() +{ + HaloLayers halo_layers(rows(), cols()); + std::vector send_requests = inform_neighbors(); + std::vector recv_requests = receive_halos(halo_layers); + + std::vector recv_status(recv_requests.size()); + MPI_Waitall(recv_requests.size(), recv_requests.data(), recv_status.data()); + + std::vector send_status(send_requests.size()); + MPI_Waitall(send_requests.size(), send_requests.data(), send_status.data()); + + merge_halos(halo_layers); +} + +void SuperGrid::merge_halos(HaloLayers halo_layers) +{ + grid_(0, 0) = halo_layers.top_left_corner; + grid_(grid_.cols(), 0) = halo_layers.top_right_corner; + grid_(0, grid_.rows()) = halo_layers.bottom_left_corner; + grid_(grid_.cols(), grid_.rows()) = halo_layers.bottom_right_corner; + + for (int col = 1; col < grid_.cols() - 1; col++) + { + grid_(col, 0) = halo_layers.top_row[col - 1]; + } + + for (int col = 1; col < grid_.cols() - 1; col++) + { + grid_(col, grid_.rows() - 1) = halo_layers.bottom_row[col - 1]; + } + + for (int row = 1; row < grid_.rows() - 1; row++) + { + grid_(0, row) = halo_layers.left_row[row - 1]; + } + + for (int row = 1; row < grid_.rows() - 1; row++) + { + grid_(grid_.cols() - 1, row) = halo_layers.right_row[row - 1]; + } +} + +const Matrix SuperGrid::get_grid() const +{ + return grid_; +} \ No newline at end of file diff --git a/lab11/game_of_life/super_grid.h b/lab11/game_of_life/super_grid.h index 9736366..83859f9 100644 --- a/lab11/game_of_life/super_grid.h +++ b/lab11/game_of_life/super_grid.h @@ -5,22 +5,50 @@ #include #include -class Neighbors { - public: - int top_left, top, top_right; - int left, right; - int bottom_left, bottom, bottom_right; +class HaloLayers +{ +public: + std::vector top_row; + std::vector right_row; + std::vector bottom_row; + std::vector left_row; - bool operator==(const Neighbors& other) const { - return top_left == other.top_left && - top == other.top && - top_right == other.top_right && - left == other.left && - right == other.right && - bottom_left == other.bottom_left && - bottom == other.bottom && - bottom_right == other.bottom_right; - } + double top_right_corner; + double bottom_right_corner; + double top_left_corner; + double bottom_left_corner; + + HaloLayers(int row_size = 0, int col_size = 0) + : top_row(col_size), + right_row(row_size), + bottom_row(col_size), + left_row(row_size), + top_right_corner(0.0), + bottom_right_corner(0.0), + top_left_corner(0.0), + bottom_left_corner(0.0) + { + } +}; + +class Neighbors +{ +public: + int top_left, top, top_right; + int left, right; + int bottom_left, bottom, bottom_right; + + bool operator==(const Neighbors &other) const + { + return top_left == other.top_left && + top == other.top && + top_right == other.top_right && + left == other.left && + right == other.right && + bottom_left == other.bottom_left && + bottom == other.bottom && + bottom_right == other.bottom_right; + } Neighbors() : top_left(-1), top(-1), top_right(-1), @@ -28,7 +56,8 @@ class Neighbors { bottom_left(-1), bottom(-1), bottom_right(-1) {} }; -class SuperGrid { +class SuperGrid +{ public: static SuperGrid zeros(int rows, int cols, MPI_Comm communicator); @@ -38,6 +67,7 @@ public: const double &operator()(int i, int j) const; const Matrix get_matrix() const; + const Matrix get_grid() const; int rows() const; int cols() const; @@ -48,35 +78,59 @@ public: MPI_Comm &get_communicator(); void set_communicator(MPI_Comm communicator); + void update(); + std::vector receive_halos(HaloLayers halo_layers); + std::vector inform_neighbors(); + private: Matrix grid_; MPI_Comm comm_; Neighbors neighbors_; + int rank_; + + std::vector get_top_row(); + std::vector get_right_row(); + std::vector get_bottom_row(); + std::vector get_left_row(); + + double get_top_right_corner(); + double get_bottom_right_corner(); + double get_top_left_corner(); + double get_bottom_left_corner(); + + void merge_halos(HaloLayers halo_layers); }; inline SuperGrid::SuperGrid(const Matrix &other) : grid_( Matrix::zeros(other.rows() + 2, other.cols() + 2)), - neighbors_(Neighbors()) // initialize grid_ + neighbors_(Neighbors()) // initialize grid_ { - for (int i = 0; i < other.rows(); i++) { - for (int j = 0; j < other.cols(); j++) { + for (int i = 0; i < other.rows(); i++) + { + for (int j = 0; j < other.cols(); j++) + { grid_(i + 1, j + 1) = other(i, j); // copy into grid_ directly } } + MPI_Comm_rank(MPI_COMM_WORLD, &rank_); } -inline SuperGrid SuperGrid::zeros(int rows, int cols, MPI_Comm communicator) { +inline SuperGrid SuperGrid::zeros(int rows, int cols, MPI_Comm communicator) +{ SuperGrid grid = SuperGrid(Matrix::zeros(rows, cols)); grid.set_communicator(communicator); + grid.find_neighbors(); return grid; } -inline double &SuperGrid::operator()(int i, int j) { +inline double &SuperGrid::operator()(int i, int j) +{ return this->grid_(i + 1, j + 1); } -inline const double &SuperGrid::operator()(int i, int j) const { +inline const double &SuperGrid::operator()(int i, int j) const +{ return this->grid_(i + 1, j + 1); } @@ -84,11 +138,14 @@ inline int SuperGrid::rows() const { return this->grid_.rows() - 2; } inline int SuperGrid::cols() const { return this->grid_.cols() - 2; } -inline const Matrix SuperGrid::get_matrix() const { +inline const Matrix SuperGrid::get_matrix() const +{ Matrix mat = Matrix::zeros(this->rows(), this->cols()); - for (int i = 0; i < this->rows(); i++) { - for (int j = 0; j < this->rows(); j++) { + for (int i = 0; i < this->rows(); i++) + { + for (int j = 0; j < this->rows(); j++) + { mat(i, j) = this->grid_(i + 1, j + 1); } } @@ -98,41 +155,57 @@ inline const Matrix SuperGrid::get_matrix() const { inline MPI_Comm &SuperGrid::get_communicator() { return this->comm_; } -inline void SuperGrid::set_communicator(MPI_Comm communicator) { +inline void SuperGrid::set_communicator(MPI_Comm communicator) +{ this->comm_ = communicator; } -inline void SuperGrid::find_neighbors() { - if (this->comm_ == MPI_COMM_NULL) { +inline void SuperGrid::find_neighbors() +{ + if (this->comm_ == MPI_COMM_NULL) + { std::cerr << "Communicator is NULL!\n"; } int rank; MPI_Comm_rank(this->comm_, &rank); int coords[2]; MPI_Cart_coords(this->comm_, rank, 2, coords); - for (int dx = -1; dx <= 1; ++dx) { - for (int dy = -1; dy <= 1; ++dy) { - if (dx == 0 && dy == 0) continue; // skip self + for (int dx = -1; dx <= 1; ++dx) + { + for (int dy = -1; dy <= 1; ++dy) + { + if (dx == 0 && dy == 0) + continue; // skip self - int neighbor_coords[2] = { coords[0] + dx, coords[1] + dy }; + int neighbor_coords[2] = {coords[0] + dx, coords[1] + dy}; int neighbor_rank; int err = MPI_Cart_rank(this->comm_, neighbor_coords, &neighbor_rank); - if (err != MPI_SUCCESS) continue; // skip invalid neighbors (if non-periodic) + if (err != MPI_SUCCESS) + continue; // skip invalid neighbors (if non-periodic) - if (dx == -1 && dy == -1) neighbors_.top_left = neighbor_rank; - if (dx == -1 && dy == 0) neighbors_.top = neighbor_rank; - if (dx == -1 && dy == 1) neighbors_.top_right = neighbor_rank; - if (dx == 0 && dy == -1) neighbors_.left = neighbor_rank; - if (dx == 0 && dy == 1) neighbors_.right = neighbor_rank; - if (dx == 1 && dy == -1) neighbors_.bottom_left = neighbor_rank; - if (dx == 1 && dy == 0) neighbors_.bottom = neighbor_rank; - if (dx == 1 && dy == 1) neighbors_.bottom_right = neighbor_rank; + if (dx == -1 && dy == -1) + neighbors_.top_left = neighbor_rank; + if (dx == -1 && dy == 0) + neighbors_.top = neighbor_rank; + if (dx == -1 && dy == 1) + neighbors_.top_right = neighbor_rank; + if (dx == 0 && dy == -1) + neighbors_.left = neighbor_rank; + if (dx == 0 && dy == 1) + neighbors_.right = neighbor_rank; + if (dx == 1 && dy == -1) + neighbors_.bottom_left = neighbor_rank; + if (dx == 1 && dy == 0) + neighbors_.bottom = neighbor_rank; + if (dx == 1 && dy == 1) + neighbors_.bottom_right = neighbor_rank; } } } -inline Neighbors SuperGrid::get_neighbors() { +inline Neighbors SuperGrid::get_neighbors() +{ return this->neighbors_; } diff --git a/lab11/game_of_life/test.cpp b/lab11/game_of_life/test.cpp index 72b7a7f..27ef00d 100644 --- a/lab11/game_of_life/test.cpp +++ b/lab11/game_of_life/test.cpp @@ -4,6 +4,7 @@ #include "matrix.h" #include "super_grid.h" #include "utils.h" +#include Matrix init_step(SuperGrid start) { @@ -12,9 +13,30 @@ Matrix init_step(SuperGrid start) return gol.getGrid(); } +SuperGrid init() +{ + MPI_Comm comm_; + int num_procs = 16; + MPIGridSize mpiProcs = {4, 4}; + MPI_Dims_create(num_procs, 2, mpiProcs.data()); + + std::array periods = {1, 1}; + MPI_Cart_create(MPI_COMM_WORLD, 2, mpiProcs.data(), periods.data(), true, + &comm_); + + return SuperGrid::zeros(10, 10, comm_); +} + +TEST(initialize) +{ + int a; + MPI_Init(&a, nullptr); + check(true, true); +} + TEST(test_underpopulation) { - SuperGrid start = SuperGrid::zeros(10, 10, nullptr); + SuperGrid start = init(); start(0, 0) = 1; Matrix end = init_step(start); check(end(0, 0), 0); @@ -22,7 +44,7 @@ TEST(test_underpopulation) TEST(test_survive_2) { - SuperGrid start = SuperGrid::zeros(10, 10, nullptr); + SuperGrid start = init(); start(0, 0) = 1; start(0, 1) = 1; start(1, 0) = 1; @@ -32,7 +54,7 @@ TEST(test_survive_2) TEST(test_survive_3) { - SuperGrid start = SuperGrid::zeros(10, 10, nullptr); + SuperGrid start = init(); start(0, 0) = 1; start(1, 1) = 1; start(0, 1) = 1; @@ -43,7 +65,7 @@ TEST(test_survive_3) TEST(test_overpopulation) { - SuperGrid start = SuperGrid::zeros(10, 10, nullptr); + SuperGrid start = init(); start(1, 1) = 1; start(0, 1) = 1; start(1, 0) = 1; @@ -55,7 +77,7 @@ TEST(test_overpopulation) TEST(test_reproduction) { - SuperGrid start = SuperGrid::zeros(10, 10, nullptr); + SuperGrid start = init(); start(0, 1) = 1; start(1, 0) = 1; start(2, 1) = 1; @@ -65,7 +87,7 @@ TEST(test_reproduction) TEST(test_survive_edge) { - SuperGrid start = SuperGrid::zeros(10, 10, nullptr); + SuperGrid start = init(); start(0, 0) = 1; start(9, 0) = 1; start(0, 9) = 1; @@ -75,31 +97,18 @@ TEST(test_survive_edge) TEST(test_super_grid) { - SuperGrid su_grid = SuperGrid::zeros(10, 10, nullptr); + SuperGrid su_grid = init(); check(su_grid.rows(), 10); check(su_grid.cols(), 10); } TEST(test_find_neighbors) { - int a; - char *b[10]; - MPI_Init(&a, nullptr); - - MPI_Comm comm_; - int num_procs = 16; - MPIGridSize mpiProcs = {4, 4}; - MPI_Dims_create(num_procs, 2, mpiProcs.data()); - - std::array periods = {1, 1}; - MPI_Cart_create(MPI_COMM_WORLD, 2, mpiProcs.data(), periods.data(), true, - &comm_); - - SuperGrid su_grid = SuperGrid::zeros(10, 10, comm_); + SuperGrid su_grid = init(); su_grid.find_neighbors(); int rank; - MPI_Comm_rank(comm_, &rank); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank == 0) { Neighbors neighbors = su_grid.get_neighbors(); @@ -117,4 +126,29 @@ TEST(test_find_neighbors) MPI_Finalize(); } -int main(int argc, char *argv[]) { return 0; } +TEST(communication) +{ + SuperGrid su_grid = init(); + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank == 1) { + su_grid(0, 0) = 1; + su_grid(0, 2) = 1; + su_grid(0, 4) = 1; + } + su_grid.update(); + if (rank == 0) { + Matrix result = su_grid.get_grid(); + check(result(11, 1), 1); + check(result(11, 3), 1); + check(result(11, 5), 1); + } +} + +TEST(get_halo_layers) +{ +} + +int main(int argc, char *argv[]) { + std::cout << "main" << std::endl; + return 0; }