feat: fixed incorrect behaviour on simulation and added benchmarking code
This commit is contained in:
parent
1ce447208b
commit
98ee5fd73d
|
|
@ -1,4 +1,5 @@
|
|||
#include "simulation.h"
|
||||
#include "SDL3/SDL_timer.h"
|
||||
#include "input.h"
|
||||
#include "thread_pool.h"
|
||||
#include <SDL3/SDL_log.h>
|
||||
|
|
@ -77,10 +78,15 @@ static size_t CountNeighbors(Cell const &cell) {
|
|||
|
||||
static std::mutex underpopulatedMutex, overpopulatedMutex, bornMutex;
|
||||
|
||||
static void FindOverpopulated() {
|
||||
static void FindOverpopulated(size_t segment, size_t length) {
|
||||
overpopulatedMutex.lock();
|
||||
overpopulated.clear();
|
||||
std::ranges::copy_if(living, std::back_inserter(overpopulated),
|
||||
std::set<Cell>::iterator begin{ living.begin() };
|
||||
std::set<Cell>::iterator end{ living.begin() };
|
||||
|
||||
std::advance(begin, segment * length);
|
||||
std::advance(end, segment * length + length);
|
||||
|
||||
std::copy_if(begin, end, std::back_inserter(overpopulated),
|
||||
[&](Cell const &c) -> bool {
|
||||
size_t const neighbors{ CountNeighbors(c) };
|
||||
return neighbors > 3;
|
||||
|
|
@ -88,10 +94,16 @@ static void FindOverpopulated() {
|
|||
overpopulatedMutex.unlock();
|
||||
}
|
||||
|
||||
static void FindUnderpopulated() {
|
||||
static void FindUnderpopulated(size_t segment, size_t length) {
|
||||
uint64_t ns{ SDL_GetTicksNS() };
|
||||
underpopulatedMutex.lock();
|
||||
underpopulated.clear();
|
||||
std::ranges::copy_if(living, std::back_inserter(underpopulated),
|
||||
std::set<Cell>::iterator begin{ living.begin() };
|
||||
std::set<Cell>::iterator end{ living.begin() };
|
||||
|
||||
std::advance(begin, segment * length);
|
||||
std::advance(end, segment * length + length);
|
||||
|
||||
std::copy_if(begin, end, std::back_inserter(underpopulated),
|
||||
[&](Cell const &c) -> bool {
|
||||
size_t const neighbors{ CountNeighbors(c) };
|
||||
return neighbors < 2;
|
||||
|
|
@ -99,11 +111,17 @@ static void FindUnderpopulated() {
|
|||
underpopulatedMutex.unlock();
|
||||
}
|
||||
|
||||
static void FindBorn() {
|
||||
static void FindBorn(size_t segment, size_t length) {
|
||||
uint64_t ns{ SDL_GetTicksNS() };
|
||||
bornMutex.lock();
|
||||
born.clear();
|
||||
for (Cell const &cell : living) {
|
||||
std::vector<Cell> neighbors{ NeighborSet(cell) };
|
||||
std::set<Cell>::iterator itr{ living.begin() };
|
||||
std::set<Cell>::iterator end{ living.begin() };
|
||||
|
||||
std::advance(itr, segment * length);
|
||||
std::advance(end, segment * length + length);
|
||||
|
||||
for (;itr != end; ++itr) {
|
||||
std::vector<Cell> neighbors{ NeighborSet(*itr) };
|
||||
std::ranges::copy_if(neighbors, std::back_inserter(born),
|
||||
[&](Cell const &c) -> bool {
|
||||
size_t const neighbors{ CountNeighbors(c) };
|
||||
|
|
@ -113,20 +131,43 @@ static void FindBorn() {
|
|||
bornMutex.unlock();
|
||||
}
|
||||
|
||||
#define MULTITHREADING 0
|
||||
static uint64_t generationTime{ 0 };
|
||||
static bool logGenerationTime{ false };
|
||||
|
||||
static void PopulateChanges() {
|
||||
#if 1
|
||||
threading::tasks.ScheduleTask(&FindOverpopulated);
|
||||
threading::tasks.ScheduleTask(&FindUnderpopulated);
|
||||
threading::tasks.ScheduleTask(&FindBorn);
|
||||
generationTime = SDL_GetTicksNS();
|
||||
logGenerationTime = true;
|
||||
#if MULTITHREADING
|
||||
constexpr size_t split{ 2 };
|
||||
size_t const seg_length{ living.size() / split };
|
||||
for (size_t i{ 0 }; i < split; ++i) {
|
||||
threading::tasks.ScheduleTask(std::bind(FindOverpopulated, i, seg_length));
|
||||
threading::tasks.ScheduleTask(std::bind(FindUnderpopulated, i, seg_length));
|
||||
threading::tasks.ScheduleTask(std::bind(FindBorn, i, seg_length));
|
||||
}
|
||||
#else
|
||||
FindOverpopulated();
|
||||
FindUnderpopulated();
|
||||
FindBorn();
|
||||
FindOverpopulated(0, living.size());
|
||||
FindUnderpopulated(0, living.size());
|
||||
FindBorn(0, living.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
void InitializeRandom(size_t livingChance, int64_t fillArea) {
|
||||
underpopulatedMutex.lock();
|
||||
underpopulated.clear();
|
||||
underpopulatedMutex.unlock();
|
||||
|
||||
overpopulatedMutex.lock();
|
||||
overpopulated.clear();
|
||||
overpopulatedMutex.unlock();
|
||||
|
||||
bornMutex.lock();
|
||||
born.clear();
|
||||
bornMutex.unlock();
|
||||
|
||||
living.clear();
|
||||
|
||||
Cell itr{ 0, 0 };
|
||||
while (itr.y < fillArea) {
|
||||
if (std::rand() % livingChance == 0 ) {
|
||||
|
|
@ -143,20 +184,28 @@ void InitializeRandom(size_t livingChance, int64_t fillArea) {
|
|||
|
||||
void Step() {
|
||||
underpopulatedMutex.lock();
|
||||
overpopulatedMutex.lock();
|
||||
bornMutex.lock();
|
||||
|
||||
for (Cell const &cell : underpopulated) {
|
||||
living.erase(cell);
|
||||
}
|
||||
underpopulatedMutex.unlock();
|
||||
overpopulatedMutex.lock();
|
||||
underpopulated.clear();
|
||||
|
||||
for (Cell const &cell : overpopulated) {
|
||||
living.erase(cell);
|
||||
}
|
||||
overpopulatedMutex.unlock();
|
||||
bornMutex.lock();
|
||||
overpopulated.clear();
|
||||
|
||||
for (Cell const &cell : born) {
|
||||
living.insert(cell);
|
||||
}
|
||||
born.clear();
|
||||
|
||||
underpopulatedMutex.unlock();
|
||||
overpopulatedMutex.unlock();
|
||||
bornMutex.unlock();
|
||||
|
||||
PopulateChanges();
|
||||
}
|
||||
|
||||
|
|
@ -207,6 +256,11 @@ void Draw(SDL_Renderer *renderer, double cellSizePercent) {
|
|||
SDL_RenderRect(renderer, &cellRect);
|
||||
}
|
||||
bornMutex.unlock();
|
||||
|
||||
if (logGenerationTime) {
|
||||
SDL_Log("End Generation %lf", double(SDL_GetTicksNS() - generationTime) * 0.0000000001);
|
||||
logGenerationTime = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetSimulationHovered(bool value) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue