Autre session d'optimisation
This commit is contained in:
parent
b0c940f633
commit
53a8a048d9
@ -1,11 +1,9 @@
|
|||||||
#include "GOLTeamH.h"
|
#include "GOLTeamH.h"
|
||||||
|
|
||||||
|
GOLTeamH::GOLTeamH()
|
||||||
|
: mParsedRule{}
|
||||||
//Inlining des acesseur dans GOLTeam.h
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//! \brief Accesseurs retournant des informations générales sur la
|
//! \brief Accesseurs retournant des informations générales sur la
|
||||||
//! simulation en cours.
|
//! simulation en cours.
|
||||||
@ -146,7 +144,7 @@ bool GOLTeamH::setRule(std::string const& rule)
|
|||||||
{
|
{
|
||||||
mRule = rule;
|
mRule = rule;
|
||||||
bool firstPart{ true };
|
bool firstPart{ true };
|
||||||
uint16_t parsedRuleRevive{}, parsedRuleSurvive{};
|
uint32_t parsedRule{};
|
||||||
|
|
||||||
// On vérifie que la chaine de charactères contient un B au début.
|
// On vérifie que la chaine de charactères contient un B au début.
|
||||||
// 5 = taille minimale
|
// 5 = taille minimale
|
||||||
@ -160,9 +158,9 @@ bool GOLTeamH::setRule(std::string const& rule)
|
|||||||
// Si c'est un chiffre, on continue en enregistrant la valeur.
|
// Si c'est un chiffre, on continue en enregistrant la valeur.
|
||||||
if (opt.has_value()) {
|
if (opt.has_value()) {
|
||||||
if (firstPart)
|
if (firstPart)
|
||||||
parsedRuleRevive |= 1u << opt.value();
|
parsedRule |= 1u << opt.value();
|
||||||
else
|
else
|
||||||
parsedRuleSurvive |= 1u << opt.value();
|
parsedRule |= 1u << (opt.value() + 16);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -179,8 +177,7 @@ bool GOLTeamH::setRule(std::string const& rule)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mParsedRuleRevive = parsedRuleRevive;
|
mParsedRule |= parsedRule;
|
||||||
mParsedRuleSurvive = parsedRuleSurvive;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,56 +381,61 @@ void GOLTeamH::processOneStep()
|
|||||||
if (mBorderManagement == GOL::BorderManagement::foreverDead) {
|
if (mBorderManagement == GOL::BorderManagement::foreverDead) {
|
||||||
size_t aliveCount{};
|
size_t aliveCount{};
|
||||||
size_t offset{ width() + 2 };
|
size_t offset{ width() + 2 };
|
||||||
auto* ptrGrid{ &grid[0] }; // Pointeur qui se promène en mémoire.
|
auto width{ mData.width() }, height{ mData.height() };
|
||||||
auto* const ptrGridInt{ &intGrid[0] }; // Pointeur statique pour des calculs.
|
|
||||||
|
|
||||||
for (size_t i{}; i < mData.realSize() - offset - 1; ++i) {
|
// Index commence à la première case qui n'est pas dans le border
|
||||||
|
auto* ptrGridInt{ &intGrid[width + 3] }; // Pointeur du tableau intermédiaire.
|
||||||
|
auto* ptrGrid{ &grid[width + 3] }; // Pointeur qui se promène en mémoire.
|
||||||
|
|
||||||
if (mData.isInBorder(i)) {
|
for (size_t j{}; j < height; ++j) {
|
||||||
|
for (size_t i{}; i < width; ++i) {
|
||||||
|
|
||||||
|
aliveCount = 0;
|
||||||
|
|
||||||
|
// Top
|
||||||
|
ptrGrid -= offset + 1;
|
||||||
|
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
||||||
ptrGrid++;
|
ptrGrid++;
|
||||||
continue;
|
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
||||||
|
ptrGrid++;
|
||||||
|
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
||||||
|
|
||||||
|
// Milieu
|
||||||
|
ptrGrid += offset - 2;
|
||||||
|
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
||||||
|
ptrGrid += 2;
|
||||||
|
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
||||||
|
|
||||||
|
|
||||||
|
// Dessous
|
||||||
|
ptrGrid += offset - 2;
|
||||||
|
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
||||||
|
ptrGrid++;
|
||||||
|
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
||||||
|
ptrGrid++;
|
||||||
|
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
||||||
|
|
||||||
|
// On retourne à une place plus loin qu'à l'origine.
|
||||||
|
ptrGrid -= offset;
|
||||||
|
ptrGridInt++;
|
||||||
|
|
||||||
|
// On prend avantage du fait que GOL::State::alive = 1.
|
||||||
|
//
|
||||||
|
// On évite aussi d'utiliser l'opérateur []. En profilant, nous avons vu un
|
||||||
|
// impact de performance de ~5%.
|
||||||
|
//
|
||||||
|
// On accède à la bonne partie des bits et on compare si le bit de survie/réanimation est
|
||||||
|
// présent. Voir GOLTeamH.cpp pour plus de détails.
|
||||||
|
*(ptrGridInt - 1) = static_cast<GOL::State>(
|
||||||
|
static_cast<bool>(
|
||||||
|
(mParsedRule >> static_cast<bool>(*(ptrGrid - 1)) * 16) & (1u << aliveCount)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
aliveCount = 0;
|
// On saute le border
|
||||||
|
|
||||||
// On prend avantage du fait que GOL::State::alive = 1 et donc
|
|
||||||
// on retire des branches if.
|
|
||||||
|
|
||||||
// Top
|
|
||||||
ptrGrid -= offset + 1;
|
|
||||||
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
|
||||||
ptrGrid++;
|
|
||||||
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
|
||||||
ptrGrid++;
|
|
||||||
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
|
||||||
|
|
||||||
// Milieu
|
|
||||||
ptrGrid += offset - 2;
|
|
||||||
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
|
||||||
ptrGrid += 2;
|
ptrGrid += 2;
|
||||||
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
ptrGridInt += 2;
|
||||||
|
|
||||||
|
|
||||||
// Dessous
|
|
||||||
ptrGrid += offset - 2;
|
|
||||||
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
|
||||||
ptrGrid++;
|
|
||||||
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
|
||||||
ptrGrid++;
|
|
||||||
aliveCount += static_cast<uint8_t> (*ptrGrid);
|
|
||||||
|
|
||||||
// On retourne à une place plus loin qu'à l'origine.
|
|
||||||
ptrGrid -= offset;
|
|
||||||
|
|
||||||
// On prend avantage du fait que GOL::State::alive = 1.
|
|
||||||
//
|
|
||||||
// On évite aussi d'utiliser l'opérateur []. En profilant, nous avons vu un
|
|
||||||
// impact de performance de ~5%.
|
|
||||||
if (*(ptrGrid - 1) == GOL::State::alive)
|
|
||||||
*(ptrGridInt + i) = static_cast<GOL::State>(static_cast<bool>(mParsedRuleSurvive & (1u << aliveCount)));
|
|
||||||
else
|
|
||||||
*(ptrGridInt + i) = static_cast<GOL::State>(static_cast<bool>(mParsedRuleRevive & (1u << aliveCount)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
ptrGrid = nullptr;
|
ptrGrid = nullptr;
|
||||||
|
|
||||||
@ -483,31 +485,31 @@ void GOLTeamH::updateImage(uint32_t* buffer, size_t buffer_size) const
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
auto s_ptr = buffer;
|
auto s_ptr = buffer;
|
||||||
auto e_ptr = &buffer[buffer_size];
|
|
||||||
auto& grid = mData.data();
|
auto& grid = mData.data();
|
||||||
|
auto width{ mData.width() }, height{ mData.height() };
|
||||||
|
auto* ptrGrid{ &grid[width + 3] }; // Pointeur qui se promène en mémoire.
|
||||||
|
|
||||||
// On itère sur chaque éléments du tableau et on associe la couleur.
|
// On itère sur chaque éléments du tableau et on associe la couleur.
|
||||||
for (size_t index{ width() + 2 }; // On ignore la ligne du bas.
|
for (size_t j{}; j < height; ++j) {
|
||||||
index < (width() + 2) * (height() + 1); // On ignore la ligne du haut.
|
for (size_t i{}; i < width; ++i) {
|
||||||
index++) {
|
auto var = static_cast<uint8_t>(*ptrGrid);
|
||||||
|
|
||||||
if (mData.isInBorder(index))
|
*s_ptr &= 0; // Clear
|
||||||
continue;
|
*s_ptr |= MAX_ALPHA << 24; // Alpha = 255
|
||||||
|
|
||||||
auto var = static_cast<uint8_t>(grid[index]);
|
*s_ptr |= mAliveColor.red * var << 16;
|
||||||
|
*s_ptr |= mAliveColor.green * var << 8;
|
||||||
|
*s_ptr |= mAliveColor.blue * var;
|
||||||
|
|
||||||
*s_ptr &= 0; // Clear
|
*s_ptr |= mDeadColor.red * (1 - var) << 16;
|
||||||
*s_ptr |= MAX_ALPHA << 24; // Alpha = 255
|
*s_ptr |= mDeadColor.green * (1 - var) << 8;
|
||||||
|
*s_ptr |= mDeadColor.blue * (1 - var);
|
||||||
|
|
||||||
*s_ptr |= mAliveColor.red * var << 16;
|
s_ptr++;
|
||||||
*s_ptr |= mAliveColor.green * var << 8;
|
ptrGrid++;
|
||||||
*s_ptr |= mAliveColor.blue * var;
|
}
|
||||||
|
ptrGrid += 2;
|
||||||
*s_ptr |= mDeadColor.red * (1 - var) << 16;
|
|
||||||
*s_ptr |= mDeadColor.green * (1 - var) << 8;
|
|
||||||
*s_ptr |= mDeadColor.blue * (1 - var);
|
|
||||||
|
|
||||||
s_ptr++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ constexpr unsigned char MAX_ALPHA = 255;
|
|||||||
class GOLTeamH : public GOL
|
class GOLTeamH : public GOL
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
GOLTeamH();
|
||||||
|
|
||||||
// inline puisque trivial.
|
// inline puisque trivial.
|
||||||
size_t width() const override { return mData.width(); }
|
size_t width() const override { return mData.width(); }
|
||||||
size_t height() const override { return mData.height(); }
|
size_t height() const override { return mData.height(); }
|
||||||
@ -43,7 +45,14 @@ private:
|
|||||||
|
|
||||||
// On utilise un bitset qui contient les règles de chaque nombre.
|
// On utilise un bitset qui contient les règles de chaque nombre.
|
||||||
// On n'utilise pas std::bitset pour des raisons de performance.
|
// On n'utilise pas std::bitset pour des raisons de performance.
|
||||||
uint16_t mParsedRuleRevive, mParsedRuleSurvive;
|
//
|
||||||
|
// Le premier 8 bits (à gauche) est celui de la règle de survie alors
|
||||||
|
// qu'à droite nous avons la règle de réanimation.
|
||||||
|
// 0000000111000111 0000000110011001
|
||||||
|
// ^^^^^^^ ^^^^^^^
|
||||||
|
// Bits non utilisés
|
||||||
|
//
|
||||||
|
uint32_t mParsedRule;
|
||||||
|
|
||||||
GridTeamH mData;
|
GridTeamH mData;
|
||||||
Color mDeadColor, mAliveColor;
|
Color mDeadColor, mAliveColor;
|
||||||
|
@ -83,7 +83,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Attention: performance terrible si utilisation. Seulement lorsque vitesse
|
// Attention: performance terrible si utilisation. Seulement lorsque vitesse
|
||||||
// n'est pas demandée.
|
// n'est pas demandée, donc pas dans la boucle principale.
|
||||||
inline bool GridTeamH::isInBorder(size_t index) const
|
inline bool GridTeamH::isInBorder(size_t index) const
|
||||||
{
|
{
|
||||||
return(index % (mWidth + 2) < 1
|
return(index % (mWidth + 2) < 1
|
||||||
|
Loading…
Reference in New Issue
Block a user