Kyle Roarty has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/56909 )

Change subject: gpu-compute: Fix register checking and allocation in dyn manager
......................................................................

gpu-compute: Fix register checking and allocation in dyn manager

This patch updates the canAllocate function to account both for
the number of regions of registers that need to be allocated,
and for the fact that the registers aren't one continuous chunk.

The patch also consolidates the registers as much as possible when
a register chunk is freed. This prevents fragmentation from making
it impossible to allocate enough registers

Change-Id: Ic95cfe614d247add475f7139d3703991042f8149
---
M src/gpu-compute/dyn_pool_manager.cc
1 file changed, 64 insertions(+), 6 deletions(-)



diff --git a/src/gpu-compute/dyn_pool_manager.cc b/src/gpu-compute/dyn_pool_manager.cc
index 62a39a9..3db5e7f 100644
--- a/src/gpu-compute/dyn_pool_manager.cc
+++ b/src/gpu-compute/dyn_pool_manager.cc
@@ -93,8 +93,24 @@
 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 @@
     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 @@
             // 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 @@
     // 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<int, int>& element){
+                return element.second == firstIdx;} );
+
+    auto lastIt = std::find_if(
+            freeSpaceRecord.begin(),
+            freeSpaceRecord.end(),
+            [&](const std::pair<int, int>& 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;
 }

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/56909
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Ic95cfe614d247add475f7139d3703991042f8149
Gerrit-Change-Number: 56909
Gerrit-PatchSet: 1
Gerrit-Owner: Kyle Roarty <kyleroarty1...@gmail.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to