Skip to content
Snippets Groups Projects
Commit cea089f6 authored by Yann Boucher's avatar Yann Boucher
Browse files

Improved performance (600ms to 30ms per cycle for 1M cells

parent a829fbcc
No related branches found
No related tags found
No related merge requests found
#ifndef CONSTANTES_HPP
#define CONSTANTES_HPP
#define MAX_ETATS 32
#if MAX_ETATS > 255
#error MAX_ETATS ne tient pas dans un unsigned char
#endif
#define MAX_VOISINS 256
#endif // CONSTANTES_HPP
...@@ -31,7 +31,7 @@ class Structure; ...@@ -31,7 +31,7 @@ class Structure;
class Grid{ class Grid{
int nb_rows; int nb_rows;
int nb_col; int nb_col;
std::vector<unsigned int> matrix; std::vector<unsigned char> matrix;
public: public:
//! \brief Constructeur par défaut, avec le nombre de ligne et de colonne souhaités //! \brief Constructeur par défaut, avec le nombre de ligne et de colonne souhaités
Grid(size_t l,size_t c); Grid(size_t l,size_t c);
......
...@@ -17,9 +17,11 @@ Cette classe représente le voisinage d'une cellule. ...@@ -17,9 +17,11 @@ Cette classe représente le voisinage d'une cellule.
#include <utility> #include <utility>
#include <string> #include <string>
#include <algorithm> #include <algorithm>
#include <cstring>
#include "coord.hpp" #include "coord.hpp"
#include "state.hpp" #include "state.hpp"
#include "constantes.hpp"
using namespace std; using namespace std;
...@@ -38,18 +40,27 @@ public: ...@@ -38,18 +40,27 @@ public:
//! \brief Classe représentant un voisinage, c'est à dire une liste de cellules dont leur état et leur position. //! \brief Classe représentant un voisinage, c'est à dire une liste de cellules dont leur état et leur position.
class Neighborhood { class Neighborhood {
//! \brief vector de voisins contenant la position relative et l'état du voisin //! \brief struct nécéssaire pour éviter l'initalisation par zéro coûteuse d'un std::pair
mutable vector<pair<Coord, unsigned int>> neighborPositions; struct Cell
//! \brief Contient le nombre de voisins d'état i : counts[i] contient le nb de voisins d'état i, ou 0 si i >= counts.size() {
std::vector<unsigned> counts; Coord pos;
unsigned char state;
};
//! \brief Contient le nombre de voisins d'état i : counts[i] contient le nb de voisins d'état i, ou 0 si i >= MAX_ETATS
unsigned char counts[MAX_ETATS];
//! \brief Nombre de voisins
unsigned int neighbors;
mutable bool sorted; mutable bool sorted;
//! \brief Tableau contenant la liste des voisins
mutable Cell neighborPositions[MAX_VOISINS];
public: public:
//! \brief Initialisation du Neighborhood //! \brief Initialisation du Neighborhood
Neighborhood() Neighborhood()
{ {
neighborPositions.reserve(8); memset(counts, 0, MAX_ETATS);
counts.reserve(8); neighbors = 0;
sorted = false; sorted = false;
} }
...@@ -58,7 +69,7 @@ public: ...@@ -58,7 +69,7 @@ public:
//! \return Le nombre de voisin //! \return Le nombre de voisin
unsigned int getNb(unsigned int s) const unsigned int getNb(unsigned int s) const
{ {
if (s >= counts.size()) if (s >= MAX_ETATS)
return 0; return 0;
else else
return counts[s]; return counts[s];
...@@ -68,12 +79,13 @@ public: ...@@ -68,12 +79,13 @@ public:
//! \brief Ajoute un voisin au vecteur des voisins. Prend une coordonnée et un état en paramètre //! \brief Ajoute un voisin au vecteur des voisins. Prend une coordonnée et un état en paramètre
//! \param Coord, State : coordonée relative et état du voisin //! \param Coord, State : coordonée relative et état du voisin
//! \pre La coord ne doit pas déjà exister //! \pre La coord ne doit pas déjà exister
void addNeighbor(Coord c, unsigned int s) { void addNeighbor(Coord c, unsigned char s) {
if (s >= MAX_ETATS)
throw NeighborhoodException("Valeur d'état supérieure à l'état maximal");
sorted = false; sorted = false;
neighborPositions.push_back({c,s}); neighborPositions[neighbors++] = {c,s};
if (s >= counts.size()) ++counts[s];
counts.resize(s+1, 0);
++counts[s];
} }
//! \brief Retourne une copie du voisinage, miroir selon l'axe vertical. //! \brief Retourne une copie du voisinage, miroir selon l'axe vertical.
...@@ -85,23 +97,23 @@ public: ...@@ -85,23 +97,23 @@ public:
//! \brief Retourne le nombre de voisins dans le Neighborhood. //! \brief Retourne le nombre de voisins dans le Neighborhood.
unsigned size() const unsigned size() const
{ return neighborPositions.size(); } { return neighbors; }
//! \brief Retourne la cellule numéro i (index allant de 0 à size()-1, permettant d'indexer les cellules indépendamment de leur position //! \brief Retourne la cellule numéro i (index allant de 0 à size()-1, permettant d'indexer les cellules indépendamment de leur position
pair<Coord, unsigned int> neighbor_at_index(unsigned i) const pair<Coord, unsigned char> neighbor_at_index(unsigned i) const
{ {
if (i >= size()) if (i >= size())
throw NeighborhoodException("Index invalide\n"); throw NeighborhoodException("Index invalide\n");
if (!sorted) if (!sorted)
{ {
std::sort(neighborPositions.begin(), neighborPositions.end(), std::sort(std::begin(neighborPositions), std::begin(neighborPositions) + neighbors,
[](const pair<Coord, unsigned int>& lhs, const pair<Coord, unsigned int>& rhs) [](const Cell& lhs, const Cell& rhs)
{ {
return lhs.first < rhs.first; return lhs.pos < rhs.pos;
}); });
sorted = true; sorted = true;
} }
return neighborPositions[i]; return {neighborPositions[i].pos, neighborPositions[i].state};
} }
}; };
......
...@@ -3,9 +3,10 @@ ...@@ -3,9 +3,10 @@
Neighborhood Neighborhood::flip_vertically() const Neighborhood Neighborhood::flip_vertically() const
{ {
Neighborhood n; Neighborhood n;
for (const auto& val : neighborPositions) for (unsigned i = 0; i < size(); ++i)
{ {
n.addNeighbor(Coord{val.first.x, -val.first.y}, val.second); const auto& val = neighborPositions[i];
n.addNeighbor(Coord{val.pos.x, -val.pos.y}, val.state);
} }
return n; return n;
} }
...@@ -13,9 +14,10 @@ Neighborhood Neighborhood::flip_vertically() const ...@@ -13,9 +14,10 @@ Neighborhood Neighborhood::flip_vertically() const
Neighborhood Neighborhood::flip_horizontally() const Neighborhood Neighborhood::flip_horizontally() const
{ {
Neighborhood n; Neighborhood n;
for (const auto& val : neighborPositions) for (unsigned i = 0; i < size(); ++i)
{ {
n.addNeighbor(Coord{-val.first.x, val.first.y}, val.second); const auto& val = neighborPositions[i];
n.addNeighbor(Coord{-val.pos.x, val.pos.y}, val.state);
} }
return n; return n;
} }
...@@ -23,9 +25,10 @@ Neighborhood Neighborhood::flip_horizontally() const ...@@ -23,9 +25,10 @@ Neighborhood Neighborhood::flip_horizontally() const
Neighborhood Neighborhood::rotate90() const Neighborhood Neighborhood::rotate90() const
{ {
Neighborhood n; Neighborhood n;
for (const auto& val : neighborPositions) for (unsigned i = 0; i < size(); ++i)
{ {
n.addNeighbor(Coord{-val.first.y, val.first.x}, val.second); const auto& val = neighborPositions[i];
n.addNeighbor(Coord{-val.pos.y, val.pos.x}, val.state);
} }
return n; return n;
} }
......
...@@ -6,7 +6,7 @@ CONFIG += c++14 ...@@ -6,7 +6,7 @@ CONFIG += c++14
TEMPLATE = app TEMPLATE = app
# Optimisations, flag pour garder les infos de debug # Optimisations, flag pour garder les infos de debug
QMAKE_CXXFLAGS += -O2 -g QMAKE_CXXFLAGS += -O3 -g
# You can make your code fail to compile if it uses deprecated APIs. # You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line. # In order to do so, uncomment the following line.
...@@ -69,6 +69,7 @@ HEADERS += \ ...@@ -69,6 +69,7 @@ HEADERS += \
../include/stateColor.hpp \ ../include/stateColor.hpp \
../include/state.hpp \ ../include/state.hpp \
../include/history.h \ ../include/history.h \
../include/constantes.hpp \
../include/structurelibraryview.hpp \ ../include/structurelibraryview.hpp \
../include/transitionrule.hpp \ ../include/transitionrule.hpp \
../include/transition_rules/circulartransition.hpp \ ../include/transition_rules/circulartransition.hpp \
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment