Autre session d'optimisation

This commit is contained in:
Timothée Leclaire-Fournier 2024-01-21 12:19:40 -05:00
parent b0c940f633
commit 53a8a048d9
3 changed files with 86 additions and 75 deletions

View File

@ -1,11 +1,9 @@
#include "GOLTeamH.h"
//Inlining des acesseur dans GOLTeam.h
GOLTeamH::GOLTeamH()
: mParsedRule{}
{
}
//! \brief Accesseurs retournant des informations générales sur la
//! simulation en cours.
@ -146,7 +144,7 @@ bool GOLTeamH::setRule(std::string const& rule)
{
mRule = rule;
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.
// 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.
if (opt.has_value()) {
if (firstPart)
parsedRuleRevive |= 1u << opt.value();
parsedRule |= 1u << opt.value();
else
parsedRuleSurvive |= 1u << opt.value();
parsedRule |= 1u << (opt.value() + 16);
continue;
}
@ -179,8 +177,7 @@ bool GOLTeamH::setRule(std::string const& rule)
return false;
}
mParsedRuleRevive = parsedRuleRevive;
mParsedRuleSurvive = parsedRuleSurvive;
mParsedRule |= parsedRule;
return true;
}
@ -384,56 +381,61 @@ void GOLTeamH::processOneStep()
if (mBorderManagement == GOL::BorderManagement::foreverDead) {
size_t aliveCount{};
size_t offset{ width() + 2 };
auto* ptrGrid{ &grid[0] }; // Pointeur qui se promène en mémoire.
auto* const ptrGridInt{ &intGrid[0] }; // Pointeur statique pour des calculs.
auto width{ mData.width() }, height{ mData.height() };
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++;
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 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);
// On saute le border
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;
// 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)));
ptrGridInt += 2;
}
ptrGrid = nullptr;
@ -483,31 +485,31 @@ void GOLTeamH::updateImage(uint32_t* buffer, size_t buffer_size) const
return;
auto s_ptr = buffer;
auto e_ptr = &buffer[buffer_size];
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.
for (size_t index{ width() + 2 }; // On ignore la ligne du bas.
index < (width() + 2) * (height() + 1); // On ignore la ligne du haut.
index++) {
for (size_t j{}; j < height; ++j) {
for (size_t i{}; i < width; ++i) {
auto var = static_cast<uint8_t>(*ptrGrid);
if (mData.isInBorder(index))
continue;
*s_ptr &= 0; // Clear
*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 |= MAX_ALPHA << 24; // Alpha = 255
*s_ptr |= mDeadColor.red * (1 - var) << 16;
*s_ptr |= mDeadColor.green * (1 - var) << 8;
*s_ptr |= mDeadColor.blue * (1 - var);
*s_ptr |= mAliveColor.red * var << 16;
*s_ptr |= mAliveColor.green * var << 8;
*s_ptr |= mAliveColor.blue * var;
*s_ptr |= mDeadColor.red * (1 - var) << 16;
*s_ptr |= mDeadColor.green * (1 - var) << 8;
*s_ptr |= mDeadColor.blue * (1 - var);
s_ptr++;
s_ptr++;
ptrGrid++;
}
ptrGrid += 2;
}
}

View File

@ -12,6 +12,8 @@ constexpr unsigned char MAX_ALPHA = 255;
class GOLTeamH : public GOL
{
public:
GOLTeamH();
// inline puisque trivial.
size_t width() const override { return mData.width(); }
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 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;
Color mDeadColor, mAliveColor;

View File

@ -83,7 +83,7 @@ private:
};
// 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
{
return(index % (mWidth + 2) < 1