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