Commit 64d23777 authored by Thomas Steinreiter's avatar Thomas Steinreiter
Browse files

perfomance improvements

parent 3b77dee3
......@@ -12,47 +12,56 @@
#include "Tile.hpp"
#include "Util.hpp"
void MpiWireworld::processCell(std::size_t x, std::size_t y) {
const auto& _model = _tile.model();
const auto modelWidth = _tile.modelWidth();
void MpiWireworld::processArea(Coord start, Size size) {
auto& _model = _tile.model();
auto& _nextModel = _tile.nextModel();
const auto currentState = _model[y * modelWidth + x];
_nextModel[y * modelWidth + x] = [&]() {
switch (currentState) {
case State::ElectronHead:
return State::ElectronTail;
break;
case State::ElectronTail:
return State::Conductor;
break;
case State::Conductor: {
const auto idx = [&](std::size_t y, std::size_t x) {
return y * modelWidth + x;
};
const std::array<State, 9> mooreNeighborhood = {
_model[idx(y - 1, x - 1)], //
_model[idx(y + 0, x - 1)], //
_model[idx(y + 1, x - 1)], //
_model[idx(y - 1, x + 0)], //
_model[idx(y + 1, x + 0)], //
_model[idx(y - 1, x + 1)], //
_model[idx(y + 0, x + 1)], //
_model[idx(y + 1, x + 1)] //
};
const auto headCount =
std::count(std::begin(mooreNeighborhood),
std::end(mooreNeighborhood), State::ElectronHead);
return (1 == headCount || headCount == 2) ? State::ElectronHead
: State::Conductor;
} break;
default:
return currentState;
break;
const auto modelWidth = _tile.modelWidth();
// std::size_t is unsigned. modulo arithmetics is used for calculating the
// index
const std::size_t leftOffset = -1;
const std::size_t rightOffset = 1;
const std::size_t downOffset = modelWidth;
const std::size_t upOffset = -downOffset;
for (std::size_t y{start.Y}; y < start.Y + size.Rows; ++y) {
for (std::size_t x{start.X}; x < start.X + size.Cols; ++x) {
const auto idx = y * modelWidth + x;
const auto currentState = _model[idx];
_nextModel[idx] = [&]() {
switch (currentState) {
case State::ElectronHead:
return State::ElectronTail;
break;
case State::ElectronTail:
return State::Conductor;
break;
case State::Conductor: {
const auto isHead = [&](std::size_t idx) {
return _model[idx] == State::ElectronHead ? 1 : 0;
};
const auto headCount =
isHead(idx + leftOffset + upOffset) + //
isHead(idx + upOffset) + //
isHead(idx + rightOffset + upOffset) + //
isHead(idx + leftOffset) + //
isHead(idx + rightOffset) + //
isHead(idx + leftOffset + downOffset) + //
isHead(idx + downOffset) + //
isHead(idx + rightOffset + downOffset); //
return (1 == headCount || headCount == 2)
? State::ElectronHead
: State::Conductor;
} break;
default:
return currentState;
break;
}
}();
}
}();
}
}
MpiWireworld::MpiWireworld(const MpiEnvironment& env, const Configuration& cfg)
......@@ -79,31 +88,21 @@ void MpiWireworld::simulateStep() {
/// border area
// top
for (std::size_t x{1}; x <= _tileSize.Cols; ++x) {
const auto y = 1;
processCell(x, y);
}
processArea({1, 1}, {_tileSize.Cols, 1});
// left and right
for (std::size_t y{2}; y < _tileSize.Rows; ++y) {
const auto x1 = 1;
const auto x2 = _tileSize.Cols;
processCell(x1, y);
processCell(x2, y);
}
processArea({1, 2}, {1, _tileSize.Rows - 2});
processArea({_tileSize.Cols, 2}, {1, _tileSize.Rows - 2});
// bottom
for (std::size_t x{1}; x <= _tileSize.Cols; ++x) {
const auto y = _tileSize.Rows;
processCell(x, y);
}
processArea({1, _tileSize.Rows}, {_tileSize.Cols, 1});
// start communication of border while processing the core
auto req = _comm.AsyncCommunicate(_nextModel);
/// core
for (std::size_t y{2}; y < _tileSize.Rows; ++y) {
for (std::size_t x{2}; x < _tileSize.Cols; ++x) { processCell(x, y); }
}
processArea({2, 2}, {_tileSize.Cols - 2, _tileSize.Rows - 2});
req.Wait();
std::swap(_model, _nextModel);
......
......@@ -13,7 +13,7 @@ class MpiWireworld {
Tile _tile;
Communicator _comm;
void processCell(std::size_t x, std::size_t y);
void processArea(Coord start, Size size);
public:
MpiWireworld(const MpiEnvironment& env, const Configuration& cfg);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment