hallo layers

This commit is contained in:
WickedJack99
2025-06-16 19:38:13 +02:00
parent 6e41e6d9ed
commit 15791914e9
6 changed files with 347 additions and 67 deletions

14
.vscode/settings.json vendored
View File

@@ -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"
}
}

View File

@@ -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);

View File

@@ -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 \

View File

@@ -0,0 +1,159 @@
#include <mpi.h>
#include "super_grid.h"
std::vector<MPI_Request> SuperGrid::receive_halos(HaloLayers halo_layers)
{
std::vector<MPI_Request> 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<double> SuperGrid::get_top_row()
{
std::vector<double> row(cols());
for (int j = 0; j < cols(); ++j)
row[j] = (*this)(j, 0);
return row;
}
std::vector<double> SuperGrid::get_bottom_row()
{
std::vector<double> row(cols());
for (int j = 0; j < cols(); ++j)
row[j] = (*this)(j, rows() - 1);
return row;
}
std::vector<double> SuperGrid::get_left_row()
{
std::vector<double> col(rows());
for (int i = 0; i < rows(); ++i)
col[i] = (*this)(0, i);
return col;
}
std::vector<double> SuperGrid::get_right_row()
{
std::vector<double> 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<MPI_Request> SuperGrid::inform_neighbors()
{
std::vector<double> top_row = get_top_row();
std::vector<double> right_row = get_right_row();
std::vector<double> bottom_row = get_bottom_row();
std::vector<double> 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<MPI_Request> 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<MPI_Request> send_requests = inform_neighbors();
std::vector<MPI_Request> recv_requests = receive_halos(halo_layers);
std::vector<MPI_Status> recv_status(recv_requests.size());
MPI_Waitall(recv_requests.size(), recv_requests.data(), recv_status.data());
std::vector<MPI_Status> 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_;
}

View File

@@ -5,22 +5,50 @@
#include <cstdio>
#include <mpi.h>
class Neighbors {
public:
int top_left, top, top_right;
int left, right;
int bottom_left, bottom, bottom_right;
class HaloLayers
{
public:
std::vector<double> top_row;
std::vector<double> right_row;
std::vector<double> bottom_row;
std::vector<double> 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<MPI_Request> receive_halos(HaloLayers halo_layers);
std::vector<MPI_Request> inform_neighbors();
private:
Matrix grid_;
MPI_Comm comm_;
Neighbors neighbors_;
int rank_;
std::vector<double> get_top_row();
std::vector<double> get_right_row();
std::vector<double> get_bottom_row();
std::vector<double> 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_;
}

View File

@@ -4,6 +4,7 @@
#include "matrix.h"
#include "super_grid.h"
#include "utils.h"
#include <iostream>
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<int, 2> 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<int, 2> 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; }