From ef5bd7ec5bb23146a62fd341059e08f5c0f14f3e Mon Sep 17 00:00:00 2001 From: Artur Harasimiuk Date: Tue, 24 Apr 2018 09:39:07 +0200 Subject: [PATCH] refactor HwTS and HWPerf tag allocators - use full type specification and remove casts in MemoryManager - remove TagAllocatorBase not used any more - make TagAllocator to be profiling/instrumentation agnostic - unify UnlimitedTagCount and make part of TagAllocator Change-Id: I7b5b1ed83aa5e1f0839f611db0530d7e062a3c25 Signed-off-by: Artur Harasimiuk --- runtime/memory_manager/memory_manager.cpp | 10 +-- runtime/memory_manager/memory_manager.h | 5 +- runtime/utilities/CMakeLists.txt | 1 - runtime/utilities/tag_allocator.h | 62 +++++++------------ runtime/utilities/tag_allocator_base.h | 41 ------------ .../memory_manager/memory_manager_tests.cpp | 12 ---- unit_tests/utilities/tag_allocator_tests.cpp | 46 ++++++++------ 7 files changed, 57 insertions(+), 120 deletions(-) delete mode 100644 runtime/utilities/tag_allocator_base.h diff --git a/runtime/memory_manager/memory_manager.cpp b/runtime/memory_manager/memory_manager.cpp index b59e914621..097a8652be 100644 --- a/runtime/memory_manager/memory_manager.cpp +++ b/runtime/memory_manager/memory_manager.cpp @@ -37,6 +37,8 @@ #include namespace OCLRT { +constexpr size_t ProfilingTagCount = 512; +constexpr size_t PerfCounterTagCount = 512; struct ReusableAllocationRequirements { size_t requiredMinimalSize; @@ -265,16 +267,16 @@ void MemoryManager::freeAllocationsList(uint32_t waitTaskCount, AllocationsList TagAllocator *MemoryManager::getEventTsAllocator() { if (profilingTimeStampAllocator.get() == nullptr) { - profilingTimeStampAllocator = std::unique_ptr(new TagAllocator(this, ProfilingTagCount, 64, UnlimitedProfilingCount)); + profilingTimeStampAllocator.reset(new TagAllocator(this, ProfilingTagCount, MemoryConstants::cacheLineSize)); } - return reinterpret_cast *>(profilingTimeStampAllocator.get()); + return profilingTimeStampAllocator.get(); } TagAllocator *MemoryManager::getEventPerfCountAllocator() { if (perfCounterAllocator.get() == nullptr) { - perfCounterAllocator = std::unique_ptr(new TagAllocator(this, PerfCounterTagCount, 64, UnlimitedPerfCounterCount)); + perfCounterAllocator.reset(new TagAllocator(this, PerfCounterTagCount, MemoryConstants::cacheLineSize)); } - return reinterpret_cast *>(perfCounterAllocator.get()); + return perfCounterAllocator.get(); } void MemoryManager::pushAllocationForResidency(GraphicsAllocation *gfxAllocation) { diff --git a/runtime/memory_manager/memory_manager.h b/runtime/memory_manager/memory_manager.h index eed48b98b4..a3ec3812b3 100644 --- a/runtime/memory_manager/memory_manager.h +++ b/runtime/memory_manager/memory_manager.h @@ -26,7 +26,6 @@ #include "runtime/memory_manager/graphics_allocation.h" #include "runtime/os_interface/32bit_memory.h" #include "runtime/helpers/aligned_memory.h" -#include "runtime/utilities/tag_allocator_base.h" #include #include @@ -240,8 +239,8 @@ class MemoryManager { protected: std::recursive_mutex mtx; - std::unique_ptr profilingTimeStampAllocator; - std::unique_ptr perfCounterAllocator; + std::unique_ptr> profilingTimeStampAllocator; + std::unique_ptr> perfCounterAllocator; bool force32bitAllocations = false; bool virtualPaddingAvailable = false; GraphicsAllocation *paddingAllocation = nullptr; diff --git a/runtime/utilities/CMakeLists.txt b/runtime/utilities/CMakeLists.txt index cad5c58420..735e283a7c 100644 --- a/runtime/utilities/CMakeLists.txt +++ b/runtime/utilities/CMakeLists.txt @@ -40,7 +40,6 @@ set(RUNTIME_SRCS_UTILITIES_BASE ${CMAKE_CURRENT_SOURCE_DIR}/spinlock.h ${CMAKE_CURRENT_SOURCE_DIR}/stackvec.h ${CMAKE_CURRENT_SOURCE_DIR}/tag_allocator.h - ${CMAKE_CURRENT_SOURCE_DIR}/tag_allocator_base.h ${CMAKE_CURRENT_SOURCE_DIR}/timer_util.h ${CMAKE_CURRENT_SOURCE_DIR}/vec.h ) diff --git a/runtime/utilities/tag_allocator.h b/runtime/utilities/tag_allocator.h index 08d76517e3..66bb1306f4 100644 --- a/runtime/utilities/tag_allocator.h +++ b/runtime/utilities/tag_allocator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2017 - 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,7 +25,6 @@ #include "runtime/helpers/debug_helpers.h" #include "runtime/memory_manager/memory_manager.h" #include "runtime/utilities/idlist.h" -#include "runtime/utilities/tag_allocator_base.h" #include #include @@ -51,29 +50,21 @@ struct TagNode : public IDNode> { }; template -class TagAllocator : public TagAllocatorBase { +class TagAllocator { public: using NodeType = TagNode; - TagAllocator(MemoryManager *memMngr, size_t tagCount, size_t tagAlignment, size_t maxTagPoolCount) : memoryManager(memMngr), - maxTagPoolCount(maxTagPoolCount), - tagCount(tagCount), - tagAlignment(tagAlignment) { - if (maxTagPoolCount) { - gfxAllocations.reserve(maxTagPoolCount); - tagPoolMemory.reserve(maxTagPoolCount); - } else { - gfxAllocations.reserve(PrefferedProfilingTagPoolCount); - tagPoolMemory.reserve(PrefferedProfilingTagPoolCount); - } + TagAllocator(MemoryManager *memMngr, size_t tagCount, size_t tagAlignment) : memoryManager(memMngr), + tagCount(tagCount), + tagAlignment(tagAlignment) { populateFreeTags(); } - ~TagAllocator() override { + MOCKABLE_VIRTUAL ~TagAllocator() { cleanUpResources(); } - void cleanUpResources() override { + void cleanUpResources() { size_t size = gfxAllocations.size(); for (uint32_t i = 0; i < size; ++i) { @@ -94,8 +85,7 @@ class TagAllocator : public TagAllocatorBase { populateFreeTags(); node = freeTags.removeFrontOne().release(); } - if (node) - usedTags.pushFrontOne(*node); + usedTags.pushFrontOne(*node); return node; } @@ -105,8 +95,6 @@ class TagAllocator : public TagAllocatorBase { ((void)(usedNode)); freeTags.pushFrontOne(*node); } - size_t peekMaxTagPoolCount() { return maxTagPoolCount; } - protected: IDList freeTags; IDList usedTags; @@ -114,7 +102,6 @@ class TagAllocator : public TagAllocatorBase { std::vector tagPoolMemory; MemoryManager *memoryManager; - const size_t maxTagPoolCount; size_t tagCount; size_t tagAlignment; @@ -128,28 +115,25 @@ class TagAllocator : public TagAllocatorBase { std::unique_lock lock(allocationsMutex); - size_t tagPoolCount = gfxAllocations.size(); - if (tagPoolCount < maxTagPoolCount || maxTagPoolCount == 0) { - GraphicsAllocation *graphicsAllocation = memoryManager->allocateGraphicsMemory(allocationSizeRequired); - gfxAllocations.push_back(graphicsAllocation); + GraphicsAllocation *graphicsAllocation = memoryManager->allocateGraphicsMemory(allocationSizeRequired); + gfxAllocations.push_back(graphicsAllocation); - uintptr_t Size = graphicsAllocation->getUnderlyingBufferSize(); - uintptr_t Start = reinterpret_cast(graphicsAllocation->getUnderlyingBuffer()); - uintptr_t End = Start + Size; - size_t nodeCount = Size / tagSize; + uintptr_t Size = graphicsAllocation->getUnderlyingBufferSize(); + uintptr_t Start = reinterpret_cast(graphicsAllocation->getUnderlyingBuffer()); + uintptr_t End = Start + Size; + size_t nodeCount = Size / tagSize; - NodeType *nodesMemory = new NodeType[nodeCount]; + NodeType *nodesMemory = new NodeType[nodeCount]; - for (size_t i = 0; i < nodeCount; ++i) { - nodesMemory[i].gfxAllocation = graphicsAllocation; - nodesMemory[i].tag = reinterpret_cast(Start); - freeTags.pushTailOne(nodesMemory[i]); - Start += tagSize; - } - DEBUG_BREAK_IF(Start > End); - ((void)(End)); - tagPoolMemory.push_back(nodesMemory); + for (size_t i = 0; i < nodeCount; ++i) { + nodesMemory[i].gfxAllocation = graphicsAllocation; + nodesMemory[i].tag = reinterpret_cast(Start); + freeTags.pushTailOne(nodesMemory[i]); + Start += tagSize; } + DEBUG_BREAK_IF(Start > End); + ((void)(End)); + tagPoolMemory.push_back(nodesMemory); } }; } // namespace OCLRT diff --git a/runtime/utilities/tag_allocator_base.h b/runtime/utilities/tag_allocator_base.h deleted file mode 100644 index 98c13ed50f..0000000000 --- a/runtime/utilities/tag_allocator_base.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017, Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#pragma once - -namespace OCLRT { -constexpr size_t UnlimitedProfilingCount = 0; -constexpr size_t ProfilingTagCount = 512; -constexpr size_t PrefferedProfilingTagPoolCount = 10; - -constexpr size_t UnlimitedPerfCounterCount = 0; -constexpr size_t PerfCounterTagCount = 512; - -class TagAllocatorBase { - public: - virtual ~TagAllocatorBase(){}; - virtual void cleanUpResources() = 0; - - protected: - TagAllocatorBase() = default; -}; -} diff --git a/unit_tests/memory_manager/memory_manager_tests.cpp b/unit_tests/memory_manager/memory_manager_tests.cpp index 5b08e35f4a..f8206a4380 100644 --- a/unit_tests/memory_manager/memory_manager_tests.cpp +++ b/unit_tests/memory_manager/memory_manager_tests.cpp @@ -567,12 +567,6 @@ TEST_F(MemoryAllocatorTest, getEventTsAllocator) { EXPECT_EQ(allocator2, allocator); } -TEST_F(MemoryAllocatorTest, givenMemoryManagerWhenTagEventTsAllocatorIsCreatedItHasUnlimitedTagCount) { - TagAllocator *allocator = memoryManager->getEventTsAllocator(); - EXPECT_NE(nullptr, allocator); - EXPECT_EQ(UnlimitedProfilingCount, allocator->peekMaxTagPoolCount()); -} - TEST_F(MemoryAllocatorTest, getEventPerfCountAllocator) { TagAllocator *allocator = memoryManager->getEventPerfCountAllocator(); EXPECT_NE(nullptr, allocator); @@ -580,12 +574,6 @@ TEST_F(MemoryAllocatorTest, getEventPerfCountAllocator) { EXPECT_EQ(allocator2, allocator); } -TEST_F(MemoryAllocatorTest, givenMemoryManagerWhenTagPerfCountAllocatorIsCreatedItHasUnlimitedTagCount) { - TagAllocator *allocator = memoryManager->getEventPerfCountAllocator(); - EXPECT_NE(nullptr, allocator); - EXPECT_EQ(UnlimitedPerfCounterCount, allocator->peekMaxTagPoolCount()); -} - TEST_F(MemoryAllocatorTest, givenMemoryManagerWhensetForce32BitAllocationsIsCalledWithTrueMutlipleTimesThenAllocatorIsReused) { memoryManager->setForce32BitAllocations(true); EXPECT_NE(nullptr, memoryManager->allocator32Bit.get()); diff --git a/unit_tests/utilities/tag_allocator_tests.cpp b/unit_tests/utilities/tag_allocator_tests.cpp index c8fb29c376..7be22e9550 100644 --- a/unit_tests/utilities/tag_allocator_tests.cpp +++ b/unit_tests/utilities/tag_allocator_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2017 - 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -36,10 +36,9 @@ struct timeStamps { uint64_t end; }; -template class MockTagAllocator : public TagAllocator { public: - MockTagAllocator(MemoryManager *memMngr, size_t tagCount, size_t tagAlignment) : TagAllocator(memMngr, tagCount, tagAlignment, TemplateMaxTagPoolCount) { + MockTagAllocator(MemoryManager *memMngr, size_t tagCount, size_t tagAlignment) : TagAllocator(memMngr, tagCount, tagAlignment) { } GraphicsAllocation *getGraphicsAllocation(size_t id = 0) { @@ -73,7 +72,7 @@ class MockTagAllocator : public TagAllocator { TEST_F(TagAllocatorTest, Initialize) { - MockTagAllocator<> tagAllocator(memoryManager, 100, 64); + MockTagAllocator tagAllocator(memoryManager, 100, 64); ASSERT_NE(nullptr, tagAllocator.getGraphicsAllocation()); @@ -87,7 +86,7 @@ TEST_F(TagAllocatorTest, Initialize) { TEST_F(TagAllocatorTest, GetReturnTagCheckFreeAndUsedLists) { - MockTagAllocator<> tagAllocator(memoryManager, 10, 16); + MockTagAllocator tagAllocator(memoryManager, 10, 16); ASSERT_NE(nullptr, tagAllocator.getGraphicsAllocation()); ASSERT_NE(nullptr, tagAllocator.getFreeTagsHead()); @@ -118,7 +117,7 @@ TEST_F(TagAllocatorTest, GetReturnTagCheckFreeAndUsedLists) { TEST_F(TagAllocatorTest, TagAlignment) { size_t alignment = 64; - MockTagAllocator<> tagAllocator(memoryManager, 10, alignment); + MockTagAllocator tagAllocator(memoryManager, 10, alignment); ASSERT_NE(nullptr, tagAllocator.getFreeTagsHead()); @@ -130,31 +129,35 @@ TEST_F(TagAllocatorTest, TagAlignment) { tagAllocator.returnTag(tagNode); } -TEST_F(TagAllocatorTest, GetAllTags) { +TEST_F(TagAllocatorTest, givenTagAllocatorWhenAllNodesWereUsedThenCreateNewGraphicsAllocation) { // Big alignment to force only 4 tags size_t alignment = 1024; - MockTagAllocator<> tagAllocator(memoryManager, 4, alignment); + MockTagAllocator tagAllocator(memoryManager, 4, alignment); ASSERT_NE(nullptr, tagAllocator.getFreeTagsHead()); TagNode *tagNodes[4]; - for (int i = 0; i < 4; i++) { + for (size_t i = 0; i < 4; i++) { tagNodes[i] = tagAllocator.getTag(); EXPECT_NE(nullptr, tagNodes[i]); } + EXPECT_EQ(1u, tagAllocator.getGraphicsAllocationsCount()); + EXPECT_EQ(1u, tagAllocator.getTagPoolCount()); - TagNode *nullTag = tagAllocator.getTag(); + TagNode *tagNode = tagAllocator.getTag(); + EXPECT_NE(nullptr, tagNode); - EXPECT_EQ(nullptr, nullTag); + EXPECT_EQ(2u, tagAllocator.getGraphicsAllocationsCount()); + EXPECT_EQ(2u, tagAllocator.getTagPoolCount()); } TEST_F(TagAllocatorTest, GetTagsAndReturnInDifferentOrder) { // Big alignment to force only 4 tags size_t alignment = 1024; - MockTagAllocator<> tagAllocator(memoryManager, 4, alignment); + MockTagAllocator tagAllocator(memoryManager, 4, alignment); ASSERT_NE(nullptr, tagAllocator.getFreeTagsHead()); @@ -164,9 +167,13 @@ TEST_F(TagAllocatorTest, GetTagsAndReturnInDifferentOrder) { tagNodes[i] = tagAllocator.getTag(); EXPECT_NE(nullptr, tagNodes[i]); } + EXPECT_EQ(1u, tagAllocator.getGraphicsAllocationsCount()); + EXPECT_EQ(1u, tagAllocator.getTagPoolCount()); - TagNode *nullTag = tagAllocator.getTag(); - EXPECT_EQ(nullptr, nullTag); + TagNode *tagNode2 = tagAllocator.getTag(); + EXPECT_NE(nullptr, tagNode2); + EXPECT_EQ(2u, tagAllocator.getGraphicsAllocationsCount()); + EXPECT_EQ(2u, tagAllocator.getTagPoolCount()); IDList> &freeList = tagAllocator.getFreeTags(); bool isFoundOnFreeList = freeList.peekContains(*tagNodes[0]); @@ -195,23 +202,22 @@ TEST_F(TagAllocatorTest, GetTagsFromTwoPools) { // Big alignment to force only 1 tag size_t alignment = 4096; - MockTagAllocator<2> tagAllocator(memoryManager, 1, alignment); + MockTagAllocator tagAllocator(memoryManager, 1, alignment); ASSERT_NE(nullptr, tagAllocator.getFreeTagsHead()); TagNode *tagNode1, *tagNode2; tagNode1 = tagAllocator.getTag(); - EXPECT_NE(nullptr, tagNode1); + ASSERT_NE(nullptr, tagNode1); tagNode2 = tagAllocator.getTag(); ASSERT_NE(nullptr, tagNode2); + EXPECT_EQ(2u, tagAllocator.getGraphicsAllocationsCount()); + EXPECT_EQ(2u, tagAllocator.getTagPoolCount()); EXPECT_NE(tagNode1->getGraphicsAllocation(), tagNode2->getGraphicsAllocation()); - TagNode *nullTag = tagAllocator.getTag(); - EXPECT_EQ(nullptr, nullTag); - tagAllocator.returnTag(tagNode1); tagAllocator.returnTag(tagNode2); } @@ -220,7 +226,7 @@ TEST_F(TagAllocatorTest, CleanupResources) { // Big alignment to force only 1 tag size_t alignment = 4096; - MockTagAllocator<2> tagAllocator(memoryManager, 1, alignment); + MockTagAllocator tagAllocator(memoryManager, 1, alignment); TagNode *tagNode1, *tagNode2;