mirror of
https://github.com/intel/compute-runtime.git
synced 2025-09-15 13:01:45 +08:00
Add deferred list to TagAllocator for nodes that are not completed
Change-Id: I0672c487315a96540184eda793132c79c7777527 Signed-off-by: Dunajski, Bartosz <bartosz.dunajski@intel.com>
This commit is contained in:

committed by
sys_ocldev

parent
096fa0e64f
commit
e3df4edb90
@ -35,6 +35,7 @@ struct HwTimeStamps {
|
||||
GlobalCompleteTS = 0;
|
||||
ContextCompleteTS = 0;
|
||||
}
|
||||
bool canBeReleased() const { return true; }
|
||||
uint64_t GlobalStartTS;
|
||||
uint64_t ContextStartTS;
|
||||
uint64_t GlobalEndTS;
|
||||
|
@ -32,6 +32,7 @@ struct HwPerfCounter {
|
||||
HWPerfCounters = {};
|
||||
HWTimeStamp.initialize();
|
||||
}
|
||||
bool canBeReleased() const { return true; }
|
||||
HwPerfCounters HWPerfCounters;
|
||||
HwTimeStamps HWTimeStamp;
|
||||
};
|
||||
|
@ -41,6 +41,11 @@ class TimestampPacket {
|
||||
End
|
||||
};
|
||||
|
||||
bool canBeReleased() const {
|
||||
return data[static_cast<uint32_t>(DataIndex::ContextEnd)] != 1 &&
|
||||
data[static_cast<uint32_t>(DataIndex::GlobalEnd)] != 1;
|
||||
}
|
||||
|
||||
const uint32_t *pickDataPtr() const { return &(data[0]); }
|
||||
|
||||
uint64_t pickAddressForPipeControlWrite(WriteOperationType operationType) const {
|
||||
|
@ -86,6 +86,7 @@ class TagAllocator {
|
||||
NodeType *getTag() {
|
||||
NodeType *node = freeTags.removeFrontOne().release();
|
||||
if (!node) {
|
||||
std::unique_lock<std::mutex> lock(allocatorMutex);
|
||||
populateFreeTags();
|
||||
node = freeTags.removeFrontOne().release();
|
||||
}
|
||||
@ -97,13 +98,18 @@ class TagAllocator {
|
||||
|
||||
MOCKABLE_VIRTUAL void returnTag(NodeType *node) {
|
||||
if (node->refCount.fetch_sub(1) == 1) {
|
||||
return returnTagToPool(node);
|
||||
if (node->tag->canBeReleased()) {
|
||||
returnTagToFreePool(node);
|
||||
} else {
|
||||
returnTagToDeferredPool(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
IDList<NodeType> freeTags;
|
||||
IDList<NodeType> usedTags;
|
||||
IDList<NodeType> deferredTags;
|
||||
std::vector<GraphicsAllocation *> gfxAllocations;
|
||||
std::vector<NodeType *> tagPoolMemory;
|
||||
|
||||
@ -111,23 +117,26 @@ class TagAllocator {
|
||||
size_t tagCount;
|
||||
size_t tagAlignment;
|
||||
|
||||
std::mutex allocationsMutex;
|
||||
std::mutex allocatorMutex;
|
||||
|
||||
MOCKABLE_VIRTUAL void returnTagToPool(NodeType *node) {
|
||||
MOCKABLE_VIRTUAL void returnTagToFreePool(NodeType *node) {
|
||||
NodeType *usedNode = usedTags.removeOne(*node).release();
|
||||
DEBUG_BREAK_IF(usedNode == nullptr);
|
||||
((void)(usedNode));
|
||||
freeTags.pushFrontOne(*node);
|
||||
}
|
||||
|
||||
void populateFreeTags() {
|
||||
void returnTagToDeferredPool(NodeType *node) {
|
||||
NodeType *usedNode = usedTags.removeOne(*node).release();
|
||||
DEBUG_BREAK_IF(!usedNode);
|
||||
deferredTags.pushFrontOne(*usedNode);
|
||||
}
|
||||
|
||||
void populateFreeTags() {
|
||||
size_t tagSize = sizeof(TagType);
|
||||
tagSize = alignUp(tagSize, tagAlignment);
|
||||
size_t allocationSizeRequired = tagCount * tagSize;
|
||||
|
||||
std::unique_lock<std::mutex> lock(allocationsMutex);
|
||||
|
||||
GraphicsAllocation *graphicsAllocation = memoryManager->allocateGraphicsMemory(allocationSizeRequired);
|
||||
gfxAllocations.push_back(graphicsAllocation);
|
||||
|
||||
|
@ -1036,6 +1036,8 @@ TEST_F(EventTest, getHwTimeStampsReturnsValidPointer) {
|
||||
ASSERT_EQ(0ULL, timeStamps->GlobalCompleteTS);
|
||||
ASSERT_EQ(0ULL, timeStamps->ContextCompleteTS);
|
||||
|
||||
EXPECT_TRUE(timeStamps->canBeReleased());
|
||||
|
||||
HwTimeStamps *timeStamps2 = event->getHwTimeStamp();
|
||||
ASSERT_EQ(timeStamps, timeStamps2);
|
||||
}
|
||||
@ -1090,6 +1092,8 @@ TEST_F(EventTest, getHwPerfCounterReturnsValidPointer) {
|
||||
ASSERT_EQ(0ULL, perfCounter->HWTimeStamp.GlobalCompleteTS);
|
||||
ASSERT_EQ(0ULL, perfCounter->HWTimeStamp.ContextCompleteTS);
|
||||
|
||||
EXPECT_TRUE(perfCounter->canBeReleased());
|
||||
|
||||
HwPerfCounter *perfCounter2 = event->getHwPerfCounter();
|
||||
ASSERT_EQ(perfCounter, perfCounter2);
|
||||
}
|
||||
|
@ -57,16 +57,38 @@ struct TimestampPacketTests : public ::testing::Test {
|
||||
BaseClass::returnTag(node);
|
||||
}
|
||||
|
||||
void returnTagToPool(NodeType *node) override {
|
||||
returnToPoolTagNodes.push_back(node);
|
||||
BaseClass::returnTagToPool(node);
|
||||
void returnTagToFreePool(NodeType *node) override {
|
||||
returnedToFreePoolNodes.push_back(node);
|
||||
BaseClass::returnTagToFreePool(node);
|
||||
}
|
||||
|
||||
std::vector<NodeType *> releaseReferenceNodes;
|
||||
std::vector<NodeType *> returnToPoolTagNodes;
|
||||
std::vector<NodeType *> returnedToFreePoolNodes;
|
||||
};
|
||||
};
|
||||
|
||||
TEST_F(TimestampPacketTests, whenEndTagIsNotOneThenCanBeReleased) {
|
||||
MockTimestampPacket timestampPacket;
|
||||
auto contextEndIndex = static_cast<uint32_t>(TimestampPacket::DataIndex::ContextEnd);
|
||||
auto globalEndIndex = static_cast<uint32_t>(TimestampPacket::DataIndex::GlobalEnd);
|
||||
|
||||
timestampPacket.data[contextEndIndex] = 1;
|
||||
timestampPacket.data[globalEndIndex] = 1;
|
||||
EXPECT_FALSE(timestampPacket.canBeReleased());
|
||||
|
||||
timestampPacket.data[contextEndIndex] = 1;
|
||||
timestampPacket.data[globalEndIndex] = 0;
|
||||
EXPECT_FALSE(timestampPacket.canBeReleased());
|
||||
|
||||
timestampPacket.data[contextEndIndex] = 0;
|
||||
timestampPacket.data[globalEndIndex] = 1;
|
||||
EXPECT_FALSE(timestampPacket.canBeReleased());
|
||||
|
||||
timestampPacket.data[contextEndIndex] = 0;
|
||||
timestampPacket.data[globalEndIndex] = 0;
|
||||
EXPECT_TRUE(timestampPacket.canBeReleased());
|
||||
}
|
||||
|
||||
TEST_F(TimestampPacketTests, whenNewTagIsTakenThenReinitialize) {
|
||||
MockMemoryManager memoryManager;
|
||||
MockTagAllocator<MockTimestampPacket> allocator(&memoryManager, 1);
|
||||
@ -227,26 +249,30 @@ HWTEST_F(TimestampPacketTests, givenDebugVariableEnabledWhenEnqueueingThenObtain
|
||||
auto node2 = cmdQ->timestampPacketNode;
|
||||
EXPECT_NE(nullptr, node2);
|
||||
EXPECT_EQ(node2, cmdQ->timestampPacketNode);
|
||||
EXPECT_EQ(0u, mockTagAllocator->returnToPoolTagNodes.size()); // nothing returned. event1 owns previous node
|
||||
EXPECT_EQ(1u, mockTagAllocator->releaseReferenceNodes.size()); // cmdQ released first node
|
||||
EXPECT_EQ(0u, mockTagAllocator->returnedToFreePoolNodes.size()); // nothing returned. event1 owns previous node
|
||||
EXPECT_EQ(1u, mockTagAllocator->releaseReferenceNodes.size()); // cmdQ released first node
|
||||
EXPECT_EQ(node1, mockTagAllocator->releaseReferenceNodes.at(0));
|
||||
|
||||
EXPECT_NE(node1, node2);
|
||||
size_t dataSize = sizeof(uint32_t) * static_cast<size_t>(TimestampPacket::DataIndex::Max);
|
||||
// mark nodes as ready
|
||||
memset(const_cast<uint32_t *>(node1->tag->pickDataPtr()), 0, dataSize);
|
||||
memset(const_cast<uint32_t *>(node2->tag->pickDataPtr()), 0, dataSize);
|
||||
|
||||
clReleaseEvent(event2);
|
||||
EXPECT_EQ(0u, mockTagAllocator->returnToPoolTagNodes.size()); // nothing returned. cmdQ owns node2
|
||||
EXPECT_EQ(2u, mockTagAllocator->releaseReferenceNodes.size()); // event2 released node2
|
||||
EXPECT_EQ(0u, mockTagAllocator->returnedToFreePoolNodes.size()); // nothing returned. cmdQ owns node2
|
||||
EXPECT_EQ(2u, mockTagAllocator->releaseReferenceNodes.size()); // event2 released node2
|
||||
EXPECT_EQ(node2, mockTagAllocator->releaseReferenceNodes.at(1));
|
||||
|
||||
clReleaseEvent(event1);
|
||||
EXPECT_EQ(1u, mockTagAllocator->returnToPoolTagNodes.size()); // removed last reference on node1
|
||||
EXPECT_EQ(node1, mockTagAllocator->returnToPoolTagNodes.at(0));
|
||||
EXPECT_EQ(1u, mockTagAllocator->returnedToFreePoolNodes.size()); // removed last reference on node1
|
||||
EXPECT_EQ(node1, mockTagAllocator->returnedToFreePoolNodes.at(0));
|
||||
EXPECT_EQ(3u, mockTagAllocator->releaseReferenceNodes.size()); // event1 released node1
|
||||
EXPECT_EQ(node1, mockTagAllocator->releaseReferenceNodes.at(2));
|
||||
|
||||
cmdQ.reset(nullptr);
|
||||
EXPECT_EQ(2u, mockTagAllocator->returnToPoolTagNodes.size()); // removed last reference on node2
|
||||
EXPECT_EQ(node2, mockTagAllocator->returnToPoolTagNodes.at(1));
|
||||
EXPECT_EQ(2u, mockTagAllocator->returnedToFreePoolNodes.size()); // removed last reference on node2
|
||||
EXPECT_EQ(node2, mockTagAllocator->returnedToFreePoolNodes.at(1));
|
||||
EXPECT_EQ(4u, mockTagAllocator->releaseReferenceNodes.size()); // cmdQ released node2
|
||||
EXPECT_EQ(node2, mockTagAllocator->releaseReferenceNodes.at(3));
|
||||
}
|
||||
|
@ -35,13 +35,19 @@ struct timeStamps {
|
||||
void initialize() {
|
||||
start = 1;
|
||||
end = 2;
|
||||
release = true;
|
||||
}
|
||||
bool canBeReleased() const { return release; }
|
||||
bool release;
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
};
|
||||
|
||||
class MockTagAllocator : public TagAllocator<timeStamps> {
|
||||
public:
|
||||
using TagAllocator<timeStamps>::populateFreeTags;
|
||||
using TagAllocator<timeStamps>::deferredTags;
|
||||
|
||||
MockTagAllocator(MemoryManager *memMngr, size_t tagCount, size_t tagAlignment) : TagAllocator<timeStamps>(memMngr, tagCount, tagAlignment) {
|
||||
}
|
||||
|
||||
@ -283,3 +289,25 @@ TEST_F(TagAllocatorTest, givenMultipleReferencesOnTagWhenReleasingThenReturnWhen
|
||||
tagAllocator.returnTag(tag);
|
||||
EXPECT_EQ(nullptr, tagAllocator.getUsedTagsHead());
|
||||
}
|
||||
|
||||
TEST_F(TagAllocatorTest, givenNotReadyTagWhenReturnedThenMoveToDeferredList) {
|
||||
MockTagAllocator tagAllocator(memoryManager, 1, 1);
|
||||
auto node = tagAllocator.getTag();
|
||||
|
||||
node->tag->release = false;
|
||||
EXPECT_TRUE(tagAllocator.deferredTags.peekIsEmpty());
|
||||
tagAllocator.returnTag(node);
|
||||
EXPECT_FALSE(tagAllocator.deferredTags.peekIsEmpty());
|
||||
EXPECT_TRUE(tagAllocator.getFreeTags().peekIsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(TagAllocatorTest, givenReadyTagWhenReturnedThenMoveToFreeList) {
|
||||
MockTagAllocator tagAllocator(memoryManager, 1, 1);
|
||||
auto node = tagAllocator.getTag();
|
||||
|
||||
node->tag->release = true;
|
||||
EXPECT_TRUE(tagAllocator.deferredTags.peekIsEmpty());
|
||||
tagAllocator.returnTag(node);
|
||||
EXPECT_TRUE(tagAllocator.deferredTags.peekIsEmpty());
|
||||
EXPECT_FALSE(tagAllocator.getFreeTags().peekIsEmpty());
|
||||
}
|
||||
|
Reference in New Issue
Block a user