diff --git a/rts/Sim/Path/Default/IPathFinder.cpp b/rts/Sim/Path/Default/IPathFinder.cpp index 16010d879bd..ff0dad9178d 100644 --- a/rts/Sim/Path/Default/IPathFinder.cpp +++ b/rts/Sim/Path/Default/IPathFinder.cpp @@ -11,34 +11,51 @@ static std::vector nodeStateBuffers; static std::vector pathFinderInstances; -IPathFinder::IPathFinder(unsigned int _BLOCK_SIZE) - : BLOCK_SIZE(_BLOCK_SIZE) - , BLOCK_PIXEL_SIZE(BLOCK_SIZE * SQUARE_SIZE) - , nbrOfBlocks(mapDims.mapx / BLOCK_SIZE, mapDims.mapy / BLOCK_SIZE) - , mStartBlockIdx(0) - , mGoalBlockIdx(0) - , mGoalHeuristic(0.0f) - , maxBlocksToBeSearched(0) - , testedBlocks(0) - , instanceIndex(pathFinderInstances.size()) +void IPathFinder::InitStatic() { pathFinderInstances.reserve(8); } +void IPathFinder::KillStatic() { pathFinderInstances.clear ( ); } + + +void IPathFinder::Init(unsigned int _BLOCK_SIZE) { - pathFinderInstances.push_back(this); + { + BLOCK_SIZE = _BLOCK_SIZE; + BLOCK_PIXEL_SIZE = BLOCK_SIZE * SQUARE_SIZE; + + nbrOfBlocks.x = mapDims.mapx / BLOCK_SIZE; + nbrOfBlocks.y = mapDims.mapy / BLOCK_SIZE; + + mStartBlockIdx = 0; + mGoalBlockIdx = 0; + + mGoalHeuristic = 0.0f; + + maxBlocksToBeSearched = 0; + testedBlocks = 0; + + instanceIndex = pathFinderInstances.size(); + } + { + openBlockBuffer.Clear(); + // handled via AllocStateBuffer + // blockStates.Clear(); + openBlocks.Clear(); + dirtyBlocks.clear(); + } + { + pathFinderInstances.push_back(this); + } AllocStateBuffer(); ResetSearch(); } -IPathFinder::~IPathFinder() +void IPathFinder::Kill() { // allow our PNSB to be reused across reloads nodeStateBuffers[instanceIndex] = std::move(blockStates); } -void IPathFinder::InitStatic() { pathFinderInstances.reserve(8); } -void IPathFinder::KillStatic() { pathFinderInstances.clear ( ); } - - void IPathFinder::AllocStateBuffer() { if (instanceIndex >= nodeStateBuffers.size()) diff --git a/rts/Sim/Path/Default/IPathFinder.h b/rts/Sim/Path/Default/IPathFinder.h index b0663cae87c..dc6ee3d1bdb 100644 --- a/rts/Sim/Path/Default/IPathFinder.h +++ b/rts/Sim/Path/Default/IPathFinder.h @@ -3,8 +3,6 @@ #ifndef IPATH_FINDER_H #define IPATH_FINDER_H -#include -#include #include #include "IPath.h" @@ -19,8 +17,10 @@ class CSolidObject; class IPathFinder { public: - IPathFinder(unsigned int BLOCK_SIZE); - virtual ~IPathFinder(); + virtual ~IPathFinder() {} + + void Init(unsigned int BLOCK_SIZE); + void Kill(); static void InitStatic(); static void KillStatic(); @@ -124,22 +124,22 @@ class IPathFinder { public: // if larger than 1, this IPF is an estimator - const unsigned int BLOCK_SIZE; - const unsigned int BLOCK_PIXEL_SIZE; + unsigned int BLOCK_SIZE = 0; + unsigned int BLOCK_PIXEL_SIZE = 0; int2 nbrOfBlocks; int2 mStartBlock; - unsigned int mStartBlockIdx; - unsigned int mGoalBlockIdx; // set during each search as the square closest to the goal + unsigned int mStartBlockIdx = 0; + unsigned int mGoalBlockIdx = 0; // set during each search as the square closest to the goal // heuristic value of goalSquareIdx - float mGoalHeuristic; + float mGoalHeuristic = 0.0f; - unsigned int maxBlocksToBeSearched; - unsigned int testedBlocks; + unsigned int maxBlocksToBeSearched = 0; + unsigned int testedBlocks = 0; - unsigned int instanceIndex; + unsigned int instanceIndex = 0; PathNodeBuffer openBlockBuffer; PathNodeStateBuffer blockStates; diff --git a/rts/Sim/Path/Default/PathDataTypes.h b/rts/Sim/Path/Default/PathDataTypes.h index f4c32391efb..74737dc0069 100644 --- a/rts/Sim/Path/Default/PathDataTypes.h +++ b/rts/Sim/Path/Default/PathDataTypes.h @@ -42,7 +42,15 @@ struct lessCost: public std::binary_function { struct PathNodeBuffer { public: - PathNodeBuffer(): idx(0) {} + PathNodeBuffer() { Clear(); } + + void Clear() { + for (unsigned int i = 0; i < MAX_SEARCHED_NODES; i++) { + buffer[i] = {}; + } + + SetSize(0); + } void SetSize(unsigned int i) { idx = i; } unsigned int GetSize() const { return idx; } @@ -52,7 +60,7 @@ struct PathNodeBuffer { private: /// index of the most recently added node - unsigned int idx; + unsigned int idx = 0; PathNode buffer[MAX_SEARCHED_NODES]; }; diff --git a/rts/Sim/Path/Default/PathEstimator.cpp b/rts/Sim/Path/Default/PathEstimator.cpp index 9b319661ff6..d9ac2b93645 100644 --- a/rts/Sim/Path/Default/PathEstimator.cpp +++ b/rts/Sim/Path/Default/PathEstimator.cpp @@ -52,21 +52,36 @@ static size_t GetNumThreads() { -CPathEstimator::CPathEstimator(IPathFinder* pf, unsigned int BLOCK_SIZE, const std::string& cacheFileName, const std::string& mapFileName) - : IPathFinder(BLOCK_SIZE) - , BLOCKS_TO_UPDATE(SQUARES_TO_UPDATE / (BLOCK_SIZE * BLOCK_SIZE) + 1) - , nextOffsetMessageIdx(0) - , nextCostMessageIdx(0) - , pathChecksum(0) - , fileHashCode(CalcHash(__func__)) - , offsetBlockNum(nbrOfBlocks.x * nbrOfBlocks.y) - , costBlockNum(nbrOfBlocks.x * nbrOfBlocks.y) - , parentPathFinder(pf) - , nextPathEstimator(nullptr) - , blockUpdatePenalty(0) +void CPathEstimator::Init(IPathFinder* pf, unsigned int BLOCK_SIZE, const std::string& cacheFileName, const std::string& mapFileName) { - vertexCosts.resize(moveDefHandler.GetNumMoveDefs() * blockStates.GetSize() * PATH_DIRECTION_VERTICES, PATHCOST_INFINITY); - maxSpeedMods.resize(moveDefHandler.GetNumMoveDefs(), 0.001f); + IPathFinder::Init(BLOCK_SIZE); + + { + BLOCKS_TO_UPDATE = SQUARES_TO_UPDATE / (BLOCK_SIZE * BLOCK_SIZE) + 1; + + blockUpdatePenalty = 0; + nextOffsetMessageIdx = 0; + nextCostMessageIdx = 0; + + pathChecksum = 0; + fileHashCode = CalcHash(__func__); + + offsetBlockNum = {nbrOfBlocks.x * nbrOfBlocks.y}; + costBlockNum = {nbrOfBlocks.x * nbrOfBlocks.y}; + + parentPathFinder = pf; + nextPathEstimator = nullptr; + } + { + vertexCosts.clear(); + vertexCosts.resize(moveDefHandler.GetNumMoveDefs() * blockStates.GetSize() * PATH_DIRECTION_VERTICES, PATHCOST_INFINITY); + maxSpeedMods.clear(); + maxSpeedMods.resize(moveDefHandler.GetNumMoveDefs(), 0.001f); + + updatedBlocks.clear(); + consumedBlocks.clear(); + offsetBlocksSortedByCost.clear(); + } CPathEstimator* childPE = this; CPathEstimator* parentPE = dynamic_cast(pf); @@ -117,7 +132,7 @@ CPathEstimator::CPathEstimator(IPathFinder* pf, unsigned int BLOCK_SIZE, const s } -CPathEstimator::~CPathEstimator() +void CPathEstimator::Kill() { pcMemPool.free(pathCache[0]); pcMemPool.free(pathCache[1]); @@ -129,12 +144,15 @@ void CPathEstimator::InitEstimator(const std::string& cacheFileName, const std:: const unsigned int numThreads = GetNumThreads(); if (threads.size() != numThreads) { + threads.clear(); threads.resize(numThreads); + pathFinders.clear(); pathFinders.resize(numThreads); } // always use PF for initialization, later PE maybe used - pathFinders[0] = pfMemPool.alloc(); + // TODO: pooling these will not help much, need to reuse + pathFinders[0] = pfMemPool.alloc(true); // Not much point in multithreading these... InitBlocks(); @@ -151,8 +169,8 @@ void CPathEstimator::InitEstimator(const std::string& cacheFileName, const std:: const char* fmtStrs[4] = { "[%s] creating PE%u cache with %u PF threads (%u MB)", "[%s] creating PE%u cache with %u PF thread (%u MB)", - "[%s] writing PE%u %s-cache to file", - "[%s] written PE%u %s-cache to file", + "[%s] writing PE%u cache to file %s", + "[%s] written PE%u cache to file %s", }; { @@ -165,7 +183,7 @@ void CPathEstimator::InitEstimator(const std::string& cacheFileName, const std:: spring::barrier pathBarrier(numExtraThreads + 1); for (unsigned int i = 1; i <= numExtraThreads; i++) { - pathFinders[i] = pfMemPool.alloc(); + pathFinders[i] = pfMemPool.alloc(true); threads[i] = std::move(spring::thread(&CPathEstimator::CalcOffsetsAndPathCosts, this, i, &pathBarrier)); } diff --git a/rts/Sim/Path/Default/PathEstimator.h b/rts/Sim/Path/Default/PathEstimator.h index 45f267826b8..cb4264804c3 100644 --- a/rts/Sim/Path/Default/PathEstimator.h +++ b/rts/Sim/Path/Default/PathEstimator.h @@ -40,8 +40,8 @@ class CPathEstimator: public IPathFinder { * name of the corresponding map. * Ex. PE-name "pe" + Mapname "Desert" => "Desert.pe" */ - CPathEstimator(IPathFinder*, unsigned int BSIZE, const std::string& cacheFileName, const std::string& mapFileName); - ~CPathEstimator(); + void Init(IPathFinder*, unsigned int BSIZE, const std::string& cacheFileName, const std::string& mapFileName); + void Kill(); /** @@ -122,16 +122,18 @@ class CPathEstimator: public IPathFinder { friend class CPathManager; friend class CDefaultPathDrawer; - const unsigned int BLOCKS_TO_UPDATE; + unsigned int BLOCKS_TO_UPDATE = 0; - unsigned int nextOffsetMessageIdx; - unsigned int nextCostMessageIdx; + unsigned int nextOffsetMessageIdx = 0; + unsigned int nextCostMessageIdx = 0; - std::uint32_t pathChecksum; - std::uint32_t fileHashCode; + int blockUpdatePenalty = 0; - std::atomic offsetBlockNum; - std::atomic costBlockNum; + std::uint32_t pathChecksum = 0; + std::uint32_t fileHashCode = 0; + + std::atomic offsetBlockNum = {0}; + std::atomic costBlockNum = {0}; IPathFinder* parentPathFinder; // parent (PF if BLOCK_SIZE is 16, PE[16] if 32) CPathEstimator* nextPathEstimator; // next lower-resolution estimator @@ -145,8 +147,6 @@ class CPathEstimator: public IPathFinder { /// blocks that may need an update due to map changes std::deque updatedBlocks; - int blockUpdatePenalty; - struct SOffsetBlock { float cost; int2 offset; diff --git a/rts/Sim/Path/Default/PathFinder.cpp b/rts/Sim/Path/Default/PathFinder.cpp index ae2c531cfc6..1ecf429d949 100644 --- a/rts/Sim/Path/Default/PathFinder.cpp +++ b/rts/Sim/Path/Default/PathFinder.cpp @@ -73,13 +73,6 @@ static constexpr float3 PF_DIRECTION_VECTORS_3D[] = { }; -CPathFinder::CPathFinder(bool threadSafe): IPathFinder(1) -{ - blockCheckFunc = blockCheckFuncs[threadSafe]; - dummyCacheItem = CPathCache::CacheItem{IPath::Error, {}, {-1, -1}, {-1, -1}, -1.0f, -1}; -} - - void CPathFinder::InitStatic() { static_assert(PF_DIRECTION_COSTS[PATHOPT_LEFT ] == 1.0f, ""); static_assert(PF_DIRECTION_COSTS[PATHOPT_RIGHT ] == 1.0f, ""); @@ -117,7 +110,15 @@ void CPathFinder::InitStatic() { temp.SafeNormalize(); assert(temp == PF_DIRECTION_VECTORS_3D[i]); } +} + + +void CPathFinder::Init(bool threadSafe) +{ + IPathFinder::Init(1); + blockCheckFunc = blockCheckFuncs[threadSafe]; + dummyCacheItem = CPathCache::CacheItem{IPath::Error, {}, {-1, -1}, {-1, -1}, -1.0f, -1}; } diff --git a/rts/Sim/Path/Default/PathFinder.h b/rts/Sim/Path/Default/PathFinder.h index 4e7d2c35014..a8ddb6b9f3d 100644 --- a/rts/Sim/Path/Default/PathFinder.h +++ b/rts/Sim/Path/Default/PathFinder.h @@ -3,7 +3,6 @@ #ifndef PATH_FINDER_H #define PATH_FINDER_H -#include #include #include @@ -19,10 +18,14 @@ class CPathFinderDef; class CPathFinder: public IPathFinder { public: - CPathFinder(bool threadSafe = true); - static void InitStatic(); + CPathFinder() = default; // defer Init + CPathFinder(bool threadSafe) { Init(threadSafe); } + + void Init(bool threadSafe); + void Kill() { IPathFinder::Kill(); } + typedef CMoveMath::BlockType (*BlockCheckFunc)(const MoveDef&, int, int, const CSolidObject*); protected: diff --git a/rts/Sim/Path/Default/PathManager.cpp b/rts/Sim/Path/Default/PathManager.cpp index bee70d7caab..83da91aa2f3 100644 --- a/rts/Sim/Path/Default/PathManager.cpp +++ b/rts/Sim/Path/Default/PathManager.cpp @@ -16,6 +16,10 @@ #include "System/TimeProfiler.h" +static CPathFinder gMaxResPF; +static CPathEstimator gMedResPE; +static CPathEstimator gLowResPE; + CPathManager::CPathManager() : maxResPF(nullptr) @@ -32,9 +36,6 @@ CPathManager::CPathManager() pathHeatMap = PathHeatMap::GetInstance(); pathMap.reserve(1024); - pcMemPool.clear(); - peMemPool.clear(); - pfMemPool.clear(); // PathNode::nodePos is an ushort2, PathNode::nodeNum is an int // therefore the maximum map size is limited to 64k*64k squares @@ -43,9 +44,13 @@ CPathManager::CPathManager() CPathManager::~CPathManager() { - peMemPool.free(lowResPE); - peMemPool.free(medResPE); - pfMemPool.free(maxResPF); + lowResPE->Kill(); + medResPE->Kill(); + maxResPF->Kill(); + + maxResPF = nullptr; + medResPE = nullptr; + lowResPE = nullptr; PathHeatMap::FreeInstance(pathHeatMap); PathFlowMap::FreeInstance(pathFlowMap); @@ -56,14 +61,18 @@ std::int64_t CPathManager::Finalize() { const spring_time t0 = spring_gettime(); { + maxResPF = &gMaxResPF; + medResPE = &gMedResPE; + lowResPE = &gLowResPE; + // maxResPF only runs on the main thread, so can be unsafe - maxResPF = pfMemPool.alloc(false); - medResPE = peMemPool.alloc(maxResPF, MEDRES_PE_BLOCKSIZE, "pe", mapInfo->map.name); - lowResPE = peMemPool.alloc(medResPE, LOWRES_PE_BLOCKSIZE, "pe2", mapInfo->map.name); + maxResPF->Init(false); + medResPE->Init(maxResPF, MEDRES_PE_BLOCKSIZE, "pe", mapInfo->map.name); + lowResPE->Init(medResPE, LOWRES_PE_BLOCKSIZE, "pe2", mapInfo->map.name); - // make cached path data checksum part of synced state - // so that when any client has a corrupted / incorrect - // cache it desyncs from the start, not minutes later + // make cached path data checksum part of synced state s.t. when + // any client has a corrupted or incorrect cache it desyncs from + // the start, not minutes later { SyncedUint tmp(GetPathCheckSum()); } }