parallel-cellular-automata
Framework for building parallel cellular automata.
parallel_automaton_busyw.hpp
Go to the documentation of this file.
1 
11 #ifndef PARALLEL_CELLULAR_AUTOMATA_PARALLEL_AUTOMATON_BW_HPP
12 #define PARALLEL_CELLULAR_AUTOMATA_PARALLEL_AUTOMATON_BW_HPP
13 
14 #ifndef PARALLEL_CELLULAR_AUTOMATA_CELLULAR_AUTOMATA_HPP
15 #include "cellular_automata.hpp"
16 #endif
17 #include <barrier.hpp>
18 #include <grid.hpp>
19 #include <stdexcept>
20 #include <thread>
21 #include <threadpool.hpp>
22 #include <vector>
23 
24 using namespace std;
25 
26 namespace ca
27 {
32 namespace par
33 {
38 namespace bw
39 
40 {
41 template <typename T>
43 {
44  public:
55  CellularAutomaton(ca::Grid<T> &grid, std::function<T(T, T, T, T, T, T, T, T, T)> update_function,
56  unsigned workers = 0)
57  : grid{grid}, generation(0), update_function(update_function), pool(workers)
58  {
59 
60  this->nw = pool.get_number_workers();
61  };
69  {
70  // move what's movable and copying numeric types.
71  grid = std::move(other.grid);
72  generation = other.generation;
73  update_function = other.update_function;
74  nw = other.nw;
75  pool = std::move(other.pool);
76  // set the old object in a valid state
77  other.generation = 0;
78  }
79 
87  CellularAutomaton(const CellularAutomaton &other) = delete;
88 
96  virtual void simulate(unsigned steps = 1)
97  {
98  if (steps == 0)
99  return;
100  // allocate new grid
101  Grid<T> new_grid = Grid<T>::newWithSameSize(grid);
102 
103  ca::Barrier sync_point(nw);
104 
105  auto step_advancement_fun = [&]() {
106  grid.swap(new_grid);
107  ++generation;
108  --steps;
109  };
110 
111  // function to be run by each thread
112  auto work = [&, this](unsigned start, unsigned end) {
113  while (steps > 0)
114  {
115  for (unsigned r{start}; r < end; ++r)
116  {
117  for (unsigned c{0}; c < grid.columns(); ++c)
118  {
119  auto cell = std::make_tuple(grid(r, c));
120  new_grid(r, c) =
121  std::apply(this->update_function, std::tuple_cat(cell, get_neighborhood(r, c)));
122  }
123  }
124  sync_point.busy_wait(
125  step_advancement_fun); // this gets executed only by the last thread to reach the barrier
126  }
127  };
128 
129  std::vector<std::future<void>> results; // handles for waiting the threads
130  unsigned delta{static_cast<unsigned>(grid.rows()) / nw};
131 
132  for (unsigned i{0}; i < nw; i++) // split the grid
133  {
134  unsigned start = i * delta;
135  unsigned end = (i != (nw - 1) ? (i + 1) * delta : grid.rows());
136 
137  results.push_back(pool.submit(work, start, end));
138  }
139 
140  for (auto &r : results)
141  {
142  r.wait();
143  }
144  }
145 
151  virtual size_t get_generation() const
152  {
153  return generation;
154  }
164  friend std::ostream &operator<<(std::ostream &os, const CellularAutomaton &ca)
165  {
166 
167  return os << ca.grid;
168  }
169 
170  protected:
176 
181  size_t generation;
192  std::function<T(T, T, T, T, T, T, T, T, T)> update_function;
211  virtual std::tuple<T, T, T, T, T, T, T, T> get_neighborhood(int row, int col) const
212  {
213  unsigned rows = grid.rows();
214  unsigned columns = grid.columns();
215  T top_left, top, top_right, left, right, bottom_left, bottom, bottom_right;
216  top_left = grid((row - 1 + rows) % rows, (col - 1 + columns) % columns);
217  top = grid((row - 1 + rows) % rows, col);
218  top_right = grid((row - 1 + rows) % rows, (col + 1) % columns);
219  left = grid(row, (col - 1 + columns) % columns);
220  right = grid(row, (col + 1) % columns);
221  bottom_left = grid((row + 1) % rows, (col - 1 + columns) % columns);
222  bottom = grid((row + 1) % rows, col);
223  bottom_right = grid((row + 1) % rows, (col + 1) % columns);
224  return std::make_tuple(top_left, top, top_right, left, right, bottom_left, bottom, bottom_right);
225  };
230  unsigned nw;
231 
237 };
238 } // namespace bw
239 } // namespace par
240 } // namespace ca
241 #endif
This file contains the definition of a barrier for thread synchronization.
This header imports all the other headers of the framework.
Self-resetting synchronization barrier for threads.
Definition: barrier.hpp:27
void busy_wait()
busy wait for other threads to reach the barrier.
Definition: barrier.cpp:101
Grid of the cellular automaton.
Definition: grid.hpp:31
size_t columns() const
Returns the number of columns of the grid.
Definition: grid.hpp:200
void swap(Grid &other)
Swap the content of the grid with the one of another grid.
Definition: grid.hpp:243
size_t rows() const
Returns the number of rows of the grid.
Definition: grid.hpp:191
Work-stealing threadpool.
Definition: threadpool.hpp:51
Definition: parallel_automaton_busyw.hpp:43
Grid< T > & grid
Grid of the C.A.
Definition: parallel_automaton_busyw.hpp:175
Threadpool pool
The threadpool that will run the tasks.
Definition: parallel_automaton_busyw.hpp:236
virtual size_t get_generation() const
Get the generation of the simulation.
Definition: parallel_automaton_busyw.hpp:151
virtual std::tuple< T, T, T, T, T, T, T, T > get_neighborhood(int row, int col) const
Get the neighborhood of a cell.
Definition: parallel_automaton_busyw.hpp:211
CellularAutomaton(const CellularAutomaton &other)=delete
Deleted copy constructor.
std::function< T(T, T, T, T, T, T, T, T, T)> update_function
Function used to compute the next state of the cell.
Definition: parallel_automaton_busyw.hpp:192
size_t generation
Current generation of the grid.
Definition: parallel_automaton_busyw.hpp:181
virtual void simulate(unsigned steps=1)
Run the simulation for a given number of steps.
Definition: parallel_automaton_busyw.hpp:96
unsigned nw
Number of worker threads.
Definition: parallel_automaton_busyw.hpp:225
CellularAutomaton(CellularAutomaton &&other)
Construct a new Cellular Automaton object from another one using move semantic.
Definition: parallel_automaton_busyw.hpp:68
CellularAutomaton(ca::Grid< T > &grid, std::function< T(T, T, T, T, T, T, T, T, T)> update_function, unsigned workers=0)
Construct a new Cellular Automaton object.
Definition: parallel_automaton_busyw.hpp:55
friend std::ostream & operator<<(std::ostream &os, const CellularAutomaton &ca)
Overload of the << operator.
Definition: parallel_automaton_busyw.hpp:164
Definition of the grid of the automaton.
Namespace of the framework.
Definition: barrier.hpp:20
definition of a threadpool.