Commit a829fbcc authored by Yann Boucher's avatar Yann Boucher
Browse files

Performance improvements : 4x better for the Game of Life rule on a 1M cells grid

parent 7346c3ae
Pipeline #79263 failed with stage
......@@ -50,6 +50,13 @@ public:
//! \brief Initialise la cellule de coordonnée pos à l'état 'state'
void set_cell(Coord pos, unsigned int state)
{
// fast path
if (pos.x >= 0 && pos.y >= 0 && pos.x < nb_col && pos.y < nb_rows)
{
matrix[pos.y*nb_col + pos.x] = state;
return;
}
int i = pos.y;
int j = pos.x;
matrix[((i%nb_rows + nb_rows)%nb_rows)*nb_col
......@@ -60,6 +67,12 @@ public:
//! \brief Retourne l'état d'une cellule
//! \return Retourne l'état d'une cellule de coordonnées pos
unsigned int get_state(Coord pos)const{
// fast path
if (pos.x >= 0 && pos.y >= 0 && pos.x < nb_col && pos.y < nb_rows)
{
return matrix[pos.y*nb_col + pos.x];
}
int i = pos.y;
int j = pos.x;
return matrix[((i%nb_rows + nb_rows)%nb_rows)*nb_col
......
......@@ -7,18 +7,21 @@
Cette classe représente le voisinage d'une cellule.
**/
**/
#ifndef NEIGHBOURHOOD_HPP
#define NEIGHBOURHOOD_HPP
#include <map>
#include <vector>
#include <utility>
#include <string>
#include <algorithm>
#include "coord.hpp"
#include "state.hpp"
using namespace std;
using namespace std;
//! \brief Exception lancée lors d'une erreur de manipulation d'un voisinage.
class NeighborhoodException : public std::exception
......@@ -35,34 +38,43 @@ public:
//! \brief Classe représentant un voisinage, c'est à dire une liste de cellules dont leur état et leur position.
class Neighborhood {
//! \brief Map de voisins contenant la position relative et l'état du voisin
map<Coord, unsigned int> neighborPositions;
//! \brief vector de voisins contenant la position relative et l'état du voisin
mutable vector<pair<Coord, unsigned int>> neighborPositions;
//! \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;
mutable bool sorted;
public:
//! \brief Fonction vérifiant que la coordonnée d'un voisin que l'on souhaite ajouter dans le vecteur neighborPositions est unique
//! \param Coord : Coordonnée à comparer
//! \return retourne vrai si la coordonnée est unique sinon faux s'il existe un doublon
bool isUnique(Coord c) const;
//! \brief Retourne le nombre de voisin ayant l'état définit en paramètre
//! \param State : Etat des voisins à rechercher
//! \return Le nombre de voisin
unsigned int getNb(unsigned int s) const;
//! \brief Retourne l'état de la cellule voisine située à la coordonnée relative entrée en paramètre
//! \param Coordonnée du voisin à trouver
//! \return L'état de la cellule
unsigned int getAt(Coord c) const;
//! \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
void addNeighbor(Coord c, unsigned int s) {
if(isUnique(c))
neighborPositions[c] = s;
//! \brief Initialisation du Neighborhood
Neighborhood()
{
neighborPositions.reserve(8);
counts.reserve(8);
sorted = false;
}
//! \brief Retourne le nombre de voisin ayant l'état définit en paramètre
//! \param State : Etat des voisins à rechercher
//! \return Le nombre de voisin
unsigned int getNb(unsigned int s) const
{
if (s >= counts.size())
return 0;
else
throw NeighborhoodException("La coordonnée existe déjà. \n");
}
return counts[s];
}
//! \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
//! \pre La coord ne doit pas déjà exister
void addNeighbor(Coord c, unsigned int s) {
sorted = false;
neighborPositions.push_back({c,s});
if (s >= counts.size())
counts.resize(s+1, 0);
++counts[s];
}
//! \brief Retourne une copie du voisinage, miroir selon l'axe vertical.
Neighborhood flip_vertically() const;
......@@ -80,9 +92,16 @@ public:
{
if (i >= size())
throw NeighborhoodException("Index invalide\n");
auto it = neighborPositions.begin();
std::advance(it, i);
return *it;
if (!sorted)
{
std::sort(neighborPositions.begin(), neighborPositions.end(),
[](const pair<Coord, unsigned int>& lhs, const pair<Coord, unsigned int>& rhs)
{
return lhs.first < rhs.first;
});
sorted = true;
}
return neighborPositions[i];
}
};
......
#include "neighborhood.hpp"
unsigned int Neighborhood::getNb(unsigned int s) const
{
unsigned int res = 0;
for (auto it = neighborPositions.begin(); it != neighborPositions.end(); ++it) {
if (it->second == s) {
res++;
}
}
return res;
}
unsigned int Neighborhood::getAt(Coord c) const
{
if (!neighborPositions.count(c))
throw NeighborhoodException("Error Neighborhood::getAt");
return neighborPositions.at(c);
}
Neighborhood Neighborhood::flip_vertically() const
{
Neighborhood n;
......@@ -51,7 +30,3 @@ Neighborhood Neighborhood::rotate90() const
return n;
}
bool Neighborhood::isUnique(Coord c) const
{
return neighborPositions.count(c) == 0;
}
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