diff --git a/src/gpu-compute/dyn_pool_manager.cc b/src/gpu-compute/dyn_pool_manager.cc index 62a39a977d..3db5e7fb18 100644 --- a/src/gpu-compute/dyn_pool_manager.cc +++ b/src/gpu-compute/dyn_pool_manager.cc @@ -93,8 +93,24 @@ bool DynPoolManager::canAllocate(uint32_t numRegions, uint32_t size) { uint32_t actualSize = minAllocatedElements(size); - DPRINTF(GPUVRF,"Can Allocate %d\n",actualSize); - return (_totRegSpaceAvailable >= actualSize); + uint32_t numAvailChunks = 0; + DPRINTF(GPUVRF, "Checking if we can allocate %d regions of size %d " + "registers\n", numRegions, actualSize); + for (auto it : freeSpaceRecord) { + numAvailChunks += (it.second - it.first)/actualSize; + } + + if (numAvailChunks >= numRegions) { + DPRINTF(GPUVRF, "Able to allocate %d regions of size %d; " + "number of available regions: %d\n", + numRegions, actualSize, numAvailChunks); + return true; + } else { + DPRINTF(GPUVRF, "Unable to allocate %d regions of size %d; " + "number of available regions: %d\n", + numRegions, actualSize, numAvailChunks); + return false; + } } uint32_t @@ -105,7 +121,8 @@ DynPoolManager::allocateRegion(const uint32_t size, uint32_t actualSize = minAllocatedElements(size); auto it = freeSpaceRecord.begin(); while (it != freeSpaceRecord.end()) { - if (it->second >= actualSize) { + uint32_t curChunkSize = it->second - it->first; + if (curChunkSize >= actualSize) { // assign the next block starting from here startIdx = it->first; _regionSize = actualSize; @@ -115,14 +132,13 @@ DynPoolManager::allocateRegion(const uint32_t size, // This case sees if this chunk size is exactly equal to // the size of the requested chunk. If yes, then this can't // contribute to future requests and hence, should be removed - if (it->second == actualSize) { + if (curChunkSize == actualSize) { it = freeSpaceRecord.erase(it); // once entire freeSpaceRecord allocated, increment // reservedSpaceRecord count ++reservedSpaceRecord; } else { it->first += actualSize; - it->second -= actualSize; } break; } @@ -144,7 +160,32 @@ DynPoolManager::freeRegion(uint32_t firstIdx, // Current dynamic register allocation does not handle wraparound assert(firstIdx < lastIdx); _totRegSpaceAvailable += lastIdx-firstIdx; - freeSpaceRecord.push_back(std::make_pair(firstIdx,lastIdx-firstIdx)); + + // Consolidate with other regions. Need to check if firstIdx or lastIdx + // already exist + auto firstIt = std::find_if( + freeSpaceRecord.begin(), + freeSpaceRecord.end(), + [&](const std::pair& element){ + return element.second == firstIdx;} ); + + auto lastIt = std::find_if( + freeSpaceRecord.begin(), + freeSpaceRecord.end(), + [&](const std::pair& element){ + return element.first == lastIdx;} ); + + if (firstIt != freeSpaceRecord.end() && lastIt != freeSpaceRecord.end()) { + firstIt->second = lastIt->second; + freeSpaceRecord.erase(lastIt); + } else if (firstIt != freeSpaceRecord.end()) { + firstIt->second = lastIdx; + } else if (lastIt != freeSpaceRecord.end()) { + lastIt->first = firstIdx; + } else { + freeSpaceRecord.push_back(std::make_pair(firstIdx, lastIdx)); + } + // remove corresponding entry from reservedSpaceRecord too --reservedSpaceRecord; }