mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-05 09:09:04 +08:00
performance: redesign usm alloc reuse mechanism
Dedicated pools for different allocations size ranges. Additional reused allocations will create their own pools. Do not reuse allocations >256MB. Related-To: NEO-6893, NEO-12299, NEO-12349 Signed-off-by: Dominik Dabek <dominik.dabek@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
dfbad8029b
commit
b2fc7345cf
@@ -19,6 +19,7 @@ ApiSpecificConfig::ApiType apiTypeForUlts = ApiSpecificConfig::OCL;
|
||||
bool globalStatelessL0 = false;
|
||||
bool globalStatelessOcl = false;
|
||||
bool isStatelessCompressionSupportedForUlts = true;
|
||||
bool isDeviceUsmPoolingEnabledForUlts = true;
|
||||
|
||||
StackVec<const char *, 4> validUltL0Prefixes = {"NEO_L0_", "NEO_", ""};
|
||||
StackVec<NEO::DebugVarPrefix, 4> validUltL0PrefixTypes = {DebugVarPrefix::neoL0, DebugVarPrefix::neo, DebugVarPrefix::none};
|
||||
@@ -59,7 +60,7 @@ bool ApiSpecificConfig::isHostAllocationCacheEnabled() {
|
||||
}
|
||||
|
||||
bool ApiSpecificConfig::isDeviceUsmPoolingEnabled() {
|
||||
return false;
|
||||
return isDeviceUsmPoolingEnabledForUlts;
|
||||
}
|
||||
|
||||
bool ApiSpecificConfig::isHostUsmPoolingEnabled() {
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
|
||||
#include "shared/source/device/device.h"
|
||||
#include "shared/source/gmm_helper/gmm.h"
|
||||
#include "shared/source/helpers/api_specific_config.h"
|
||||
#include "shared/source/helpers/array_count.h"
|
||||
#include "shared/source/helpers/gfx_core_helper.h"
|
||||
#include "shared/source/memory_manager/allocations_list.h"
|
||||
#include "shared/source/memory_manager/gfx_partition.h"
|
||||
#include "shared/source/memory_manager/unified_memory_pooling.h"
|
||||
#include "shared/source/os_interface/device_factory.h"
|
||||
#include "shared/source/os_interface/driver_info.h"
|
||||
#include "shared/source/os_interface/os_context.h"
|
||||
@@ -19,6 +21,7 @@
|
||||
#include "shared/test/common/fixtures/device_fixture.h"
|
||||
#include "shared/test/common/helpers/debug_manager_state_restore.h"
|
||||
#include "shared/test/common/helpers/default_hw_info.h"
|
||||
#include "shared/test/common/helpers/raii_product_helper.h"
|
||||
#include "shared/test/common/helpers/ult_hw_config.h"
|
||||
#include "shared/test/common/helpers/variable_backup.h"
|
||||
#include "shared/test/common/mocks/mock_allocation_properties.h"
|
||||
@@ -33,8 +36,11 @@
|
||||
#include "shared/test/common/mocks/ult_device_factory.h"
|
||||
#include "shared/test/common/test_macros/hw_test.h"
|
||||
#include "shared/test/common/test_macros/test.h"
|
||||
|
||||
using namespace NEO;
|
||||
extern ApiSpecificConfig::ApiType apiTypeForUlts;
|
||||
namespace NEO {
|
||||
extern bool isDeviceUsmPoolingEnabledForUlts;
|
||||
}
|
||||
|
||||
TEST(DeviceBlitterTest, whenBlitterOperationsSupportIsDisabledThenNoInternalCopyEngineIsReturned) {
|
||||
VariableBackup<HardwareInfo> backupHwInfo(defaultHwInfo.get());
|
||||
@@ -1803,6 +1809,60 @@ TEST_F(DeviceTests, givenDebuggerRequestedByUserWhenDeviceWithSubDevicesCreatedT
|
||||
EXPECT_NE(nullptr, deviceFactory.rootDevices[0]->getL0Debugger());
|
||||
}
|
||||
|
||||
TEST_F(DeviceTests, givenNewUsmPoolingEnabledWhenDeviceInitializedThenUsmMemAllocPoolsManagerIsCreatedButNotInitialized) {
|
||||
VariableBackup<bool> backupIsDeviceUsmPoolingEnabledForUlts(&isDeviceUsmPoolingEnabledForUlts);
|
||||
isDeviceUsmPoolingEnabledForUlts = true;
|
||||
{
|
||||
DebugManagerStateRestore restorer;
|
||||
debugManager.flags.ExperimentalUSMAllocationReuseVersion.set(2);
|
||||
auto executionEnvironment = MockDevice::prepareExecutionEnvironment(defaultHwInfo.get(), 0u);
|
||||
auto mockProductHelper = new MockProductHelper;
|
||||
executionEnvironment->rootDeviceEnvironments[0]->productHelper.reset(mockProductHelper);
|
||||
mockProductHelper->isUsmPoolAllocatorSupportedResult = true;
|
||||
UltDeviceFactory deviceFactory{1, 1, *executionEnvironment};
|
||||
auto device = deviceFactory.rootDevices[0];
|
||||
auto usmMemAllocPoolsManager = device->getUsmMemAllocPoolsManager();
|
||||
ASSERT_NE(nullptr, usmMemAllocPoolsManager);
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->isInitialized());
|
||||
}
|
||||
{
|
||||
DebugManagerStateRestore restorer;
|
||||
debugManager.flags.ExperimentalUSMAllocationReuseVersion.set(-1);
|
||||
auto executionEnvironment = MockDevice::prepareExecutionEnvironment(defaultHwInfo.get(), 0u);
|
||||
auto mockProductHelper = new MockProductHelper;
|
||||
executionEnvironment->rootDeviceEnvironments[0]->productHelper.reset(mockProductHelper);
|
||||
mockProductHelper->isUsmPoolAllocatorSupportedResult = true;
|
||||
UltDeviceFactory deviceFactory{1, 1, *executionEnvironment};
|
||||
auto device = deviceFactory.rootDevices[0];
|
||||
auto usmMemAllocPoolsManager = device->getUsmMemAllocPoolsManager();
|
||||
EXPECT_EQ(nullptr, usmMemAllocPoolsManager);
|
||||
}
|
||||
{
|
||||
DebugManagerStateRestore restorer;
|
||||
debugManager.flags.ExperimentalUSMAllocationReuseVersion.set(2);
|
||||
auto executionEnvironment = MockDevice::prepareExecutionEnvironment(defaultHwInfo.get(), 0u);
|
||||
auto mockProductHelper = new MockProductHelper;
|
||||
executionEnvironment->rootDeviceEnvironments[0]->productHelper.reset(mockProductHelper);
|
||||
mockProductHelper->isUsmPoolAllocatorSupportedResult = false;
|
||||
UltDeviceFactory deviceFactory{1, 1, *executionEnvironment};
|
||||
auto device = deviceFactory.rootDevices[0];
|
||||
auto usmMemAllocPoolsManager = device->getUsmMemAllocPoolsManager();
|
||||
EXPECT_EQ(nullptr, usmMemAllocPoolsManager);
|
||||
}
|
||||
isDeviceUsmPoolingEnabledForUlts = false;
|
||||
{
|
||||
DebugManagerStateRestore restorer;
|
||||
debugManager.flags.ExperimentalUSMAllocationReuseVersion.set(2);
|
||||
auto executionEnvironment = MockDevice::prepareExecutionEnvironment(defaultHwInfo.get(), 0u);
|
||||
auto mockProductHelper = new MockProductHelper;
|
||||
executionEnvironment->rootDeviceEnvironments[0]->productHelper.reset(mockProductHelper);
|
||||
mockProductHelper->isUsmPoolAllocatorSupportedResult = true;
|
||||
UltDeviceFactory deviceFactory{1, 1, *executionEnvironment};
|
||||
auto device = deviceFactory.rootDevices[0];
|
||||
auto usmMemAllocPoolsManager = device->getUsmMemAllocPoolsManager();
|
||||
EXPECT_EQ(nullptr, usmMemAllocPoolsManager);
|
||||
}
|
||||
}
|
||||
TEST(DeviceWithoutAILTest, givenNoAILWhenCreateDeviceThenDeviceIsCreated) {
|
||||
DebugManagerStateRestore dbgRestorer;
|
||||
debugManager.flags.EnableAIL.set(false);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/helpers/aligned_memory.h"
|
||||
#include "shared/source/memory_manager/unified_memory_pooling.h"
|
||||
#include "shared/test/common/helpers/debug_manager_state_restore.h"
|
||||
#include "shared/test/common/mocks/mock_device.h"
|
||||
@@ -13,12 +14,35 @@
|
||||
#include "shared/test/common/mocks/mock_usm_memory_pool.h"
|
||||
#include "shared/test/common/mocks/ult_device_factory.h"
|
||||
#include "shared/test/common/test_macros/test.h"
|
||||
#include "shared/test/common/test_macros/test_checks_shared.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <array>
|
||||
using namespace NEO;
|
||||
|
||||
using UnifiedMemoryPoolingStaticTest = ::testing::Test;
|
||||
TEST_F(UnifiedMemoryPoolingStaticTest, givenUsmAllocPoolWhenCallingStaticMethodsThenReturnCorrectValues) {
|
||||
EXPECT_EQ(0.08, UsmMemAllocPool::getPercentOfFreeMemoryForRecycling(InternalMemoryType::deviceUnifiedMemory));
|
||||
EXPECT_EQ(0.02, UsmMemAllocPool::getPercentOfFreeMemoryForRecycling(InternalMemoryType::hostUnifiedMemory));
|
||||
EXPECT_EQ(0.00, UsmMemAllocPool::getPercentOfFreeMemoryForRecycling(InternalMemoryType::sharedUnifiedMemory));
|
||||
|
||||
EXPECT_TRUE(UsmMemAllocPool::alignmentIsAllowed(UsmMemAllocPool::chunkAlignment));
|
||||
EXPECT_TRUE(UsmMemAllocPool::alignmentIsAllowed(UsmMemAllocPool::chunkAlignment * 2));
|
||||
EXPECT_FALSE(UsmMemAllocPool::alignmentIsAllowed(UsmMemAllocPool::chunkAlignment / 2));
|
||||
|
||||
const RootDeviceIndicesContainer rootDeviceIndices;
|
||||
const std::map<uint32_t, DeviceBitfield> deviceBitfields;
|
||||
SVMAllocsManager::UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::hostUnifiedMemory, MemoryConstants::pageSize2M, rootDeviceIndices, deviceBitfields);
|
||||
EXPECT_TRUE(UsmMemAllocPool::flagsAreAllowed(unifiedMemoryProperties));
|
||||
unifiedMemoryProperties.allocationFlags.allFlags = 1u;
|
||||
unifiedMemoryProperties.allocationFlags.allAllocFlags = 0u;
|
||||
EXPECT_FALSE(UsmMemAllocPool::flagsAreAllowed(unifiedMemoryProperties));
|
||||
unifiedMemoryProperties.allocationFlags.allFlags = 0u;
|
||||
unifiedMemoryProperties.allocationFlags.allAllocFlags = 1u;
|
||||
EXPECT_FALSE(UsmMemAllocPool::flagsAreAllowed(unifiedMemoryProperties));
|
||||
}
|
||||
|
||||
using UnifiedMemoryPoolingTest = Test<SVMMemoryAllocatorFixture<true>>;
|
||||
TEST_F(UnifiedMemoryPoolingTest, givenUsmAllocPoolWhenCallingIsInitializedThenReturnCorrectValue) {
|
||||
UsmMemAllocPool usmMemAllocPool;
|
||||
@@ -31,7 +55,7 @@ TEST_F(UnifiedMemoryPoolingTest, givenUsmAllocPoolWhenCallingIsInitializedThenRe
|
||||
SVMAllocsManager::UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::hostUnifiedMemory, MemoryConstants::pageSize2M, rootDeviceIndices, deviceBitfields);
|
||||
unifiedMemoryProperties.device = device;
|
||||
|
||||
EXPECT_TRUE(usmMemAllocPool.initialize(svmManager.get(), unifiedMemoryProperties, 1 * MemoryConstants::megaByte));
|
||||
EXPECT_TRUE(usmMemAllocPool.initialize(svmManager.get(), unifiedMemoryProperties, 1 * MemoryConstants::megaByte, 0u, 1 * MemoryConstants::megaByte));
|
||||
EXPECT_TRUE(usmMemAllocPool.isInitialized());
|
||||
|
||||
usmMemAllocPool.cleanup();
|
||||
@@ -53,7 +77,7 @@ class InitializedUnifiedMemoryPoolingTest : public UnifiedMemoryPoolingTest {
|
||||
|
||||
poolMemoryProperties = std::make_unique<SVMAllocsManager::UnifiedMemoryProperties>(poolMemoryType, MemoryConstants::pageSize2M, rootDeviceIndices, deviceBitfields);
|
||||
poolMemoryProperties->device = device;
|
||||
ASSERT_EQ(!failAllocation, usmMemAllocPool.initialize(svmManager.get(), *poolMemoryProperties.get(), poolSize));
|
||||
ASSERT_EQ(!failAllocation, usmMemAllocPool.initialize(svmManager.get(), *poolMemoryProperties.get(), poolSize, 0u, poolAllocationThreshold));
|
||||
}
|
||||
void TearDown() override {
|
||||
usmMemAllocPool.cleanup();
|
||||
@@ -66,30 +90,38 @@ class InitializedUnifiedMemoryPoolingTest : public UnifiedMemoryPoolingTest {
|
||||
Device *device;
|
||||
std::unique_ptr<MockSVMAllocsManager> svmManager;
|
||||
std::unique_ptr<SVMAllocsManager::UnifiedMemoryProperties> poolMemoryProperties;
|
||||
constexpr static auto poolAllocationThreshold = 1 * MemoryConstants::megaByte;
|
||||
};
|
||||
|
||||
using InitializedHostUnifiedMemoryPoolingTest = InitializedUnifiedMemoryPoolingTest<InternalMemoryType::hostUnifiedMemory, false>;
|
||||
TEST_F(InitializedHostUnifiedMemoryPoolingTest, givenDifferentAllocationSizesWhenCallingCanBePooledThenCorrectValueIsReturned) {
|
||||
SVMAllocsManager::UnifiedMemoryProperties memoryProperties(InternalMemoryType::hostUnifiedMemory, MemoryConstants::pageSize64k, rootDeviceIndices, deviceBitfields);
|
||||
EXPECT_TRUE(usmMemAllocPool.canBePooled(UsmMemAllocPool::allocationThreshold, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(UsmMemAllocPool::allocationThreshold + 1, memoryProperties));
|
||||
EXPECT_TRUE(usmMemAllocPool.canBePooled(poolAllocationThreshold, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(poolAllocationThreshold + 1, memoryProperties));
|
||||
|
||||
memoryProperties.memoryType = InternalMemoryType::sharedUnifiedMemory;
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(UsmMemAllocPool::allocationThreshold, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(UsmMemAllocPool::allocationThreshold + 1, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(poolAllocationThreshold, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(poolAllocationThreshold + 1, memoryProperties));
|
||||
|
||||
memoryProperties.memoryType = InternalMemoryType::deviceUnifiedMemory;
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(UsmMemAllocPool::allocationThreshold, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(UsmMemAllocPool::allocationThreshold + 1, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(poolAllocationThreshold, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(poolAllocationThreshold + 1, memoryProperties));
|
||||
|
||||
memoryProperties.memoryType = InternalMemoryType::hostUnifiedMemory;
|
||||
memoryProperties.allocationFlags.allFlags = 1u;
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(UsmMemAllocPool::allocationThreshold, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(UsmMemAllocPool::allocationThreshold + 1, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(poolAllocationThreshold, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(poolAllocationThreshold + 1, memoryProperties));
|
||||
|
||||
memoryProperties.allocationFlags.allFlags = 0u;
|
||||
memoryProperties.allocationFlags.allAllocFlags = 1u;
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(UsmMemAllocPool::allocationThreshold, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(UsmMemAllocPool::allocationThreshold + 1, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(poolAllocationThreshold, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(poolAllocationThreshold + 1, memoryProperties));
|
||||
|
||||
memoryProperties.allocationFlags.allAllocFlags = 0u;
|
||||
constexpr auto notAllowedAlignment = UsmMemAllocPool::chunkAlignment / 2;
|
||||
memoryProperties.alignment = notAllowedAlignment;
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(poolAllocationThreshold, memoryProperties));
|
||||
EXPECT_FALSE(usmMemAllocPool.canBePooled(poolAllocationThreshold + 1, memoryProperties));
|
||||
}
|
||||
|
||||
TEST_F(InitializedHostUnifiedMemoryPoolingTest, givenVariousPointersWhenCallingIsInPoolAndGetOffsetInPoolThenCorrectValuesAreReturned) {
|
||||
@@ -118,7 +150,7 @@ TEST_F(InitializedHostUnifiedMemoryPoolingTest, givenAlignmentsWhenCallingAlignm
|
||||
|
||||
TEST_F(InitializedHostUnifiedMemoryPoolingTest, givenPoolableAllocationWhenUsingPoolThenAllocationIsPooledUnlessPoolIsFull) {
|
||||
SVMAllocsManager::UnifiedMemoryProperties memoryProperties(InternalMemoryType::hostUnifiedMemory, MemoryConstants::pageSize64k, rootDeviceIndices, deviceBitfields);
|
||||
const auto allocationSize = UsmMemAllocPool::allocationThreshold;
|
||||
const auto allocationSize = poolAllocationThreshold;
|
||||
const auto allocationSizeAboveThreshold = allocationSize + 1;
|
||||
EXPECT_EQ(nullptr, usmMemAllocPool.createUnifiedMemoryAllocation(allocationSizeAboveThreshold, memoryProperties));
|
||||
EXPECT_EQ(nullptr, usmMemAllocPool.allocations.get(reinterpret_cast<void *>(0x1)));
|
||||
@@ -153,7 +185,7 @@ TEST_F(InitializedHostUnifiedMemoryPoolingTest, givenPoolableAllocationWhenUsing
|
||||
|
||||
TEST_F(InitializedHostUnifiedMemoryPoolingTest, givenVariousAlignmentsWhenUsingPoolThenAddressIsAligned) {
|
||||
SVMAllocsManager::UnifiedMemoryProperties memoryProperties(InternalMemoryType::hostUnifiedMemory, 0u, rootDeviceIndices, deviceBitfields);
|
||||
const auto allocationSize = UsmMemAllocPool::allocationThreshold;
|
||||
const auto allocationSize = poolAllocationThreshold;
|
||||
|
||||
std::array<size_t, 8> alignmentsToCheck = {UsmMemAllocPool::chunkAlignment,
|
||||
UsmMemAllocPool::chunkAlignment * 2,
|
||||
@@ -164,7 +196,7 @@ TEST_F(InitializedHostUnifiedMemoryPoolingTest, givenVariousAlignmentsWhenUsingP
|
||||
UsmMemAllocPool::chunkAlignment * 64,
|
||||
UsmMemAllocPool::chunkAlignment * 128};
|
||||
for (const auto &alignment : alignmentsToCheck) {
|
||||
if (alignment > UsmMemAllocPool::allocationThreshold) {
|
||||
if (alignment > poolAllocationThreshold) {
|
||||
break;
|
||||
}
|
||||
memoryProperties.alignment = alignment;
|
||||
@@ -189,7 +221,7 @@ TEST_F(InitializedHostUnifiedMemoryPoolingTest, givenPoolableAllocationWhenGetti
|
||||
|
||||
SVMAllocsManager::UnifiedMemoryProperties memoryProperties(InternalMemoryType::hostUnifiedMemory, MemoryConstants::pageSize64k, rootDeviceIndices, deviceBitfields);
|
||||
const auto requestedAllocSize = 1 * MemoryConstants::kiloByte;
|
||||
EXPECT_GT(usmMemAllocPool.allocationThreshold, requestedAllocSize + usmMemAllocPool.chunkAlignment);
|
||||
EXPECT_GT(poolAllocationThreshold, requestedAllocSize + usmMemAllocPool.chunkAlignment);
|
||||
|
||||
// we want an allocation from the middle of the pool for testing
|
||||
auto unusedAlloc = usmMemAllocPool.createUnifiedMemoryAllocation(requestedAllocSize, memoryProperties);
|
||||
@@ -227,7 +259,7 @@ TEST_F(InitializedHostUnifiedMemoryPoolingTest, givenPoolableAllocationWhenGetti
|
||||
using InitializationFailedUnifiedMemoryPoolingTest = InitializedUnifiedMemoryPoolingTest<InternalMemoryType::hostUnifiedMemory, true>;
|
||||
TEST_F(InitializationFailedUnifiedMemoryPoolingTest, givenNotInitializedPoolWhenUsingPoolThenMethodsSucceed) {
|
||||
SVMAllocsManager::UnifiedMemoryProperties memoryProperties(InternalMemoryType::hostUnifiedMemory, MemoryConstants::pageSize64k, rootDeviceIndices, deviceBitfields);
|
||||
const auto allocationSize = UsmMemAllocPool::allocationThreshold;
|
||||
const auto allocationSize = poolAllocationThreshold;
|
||||
EXPECT_EQ(nullptr, usmMemAllocPool.createUnifiedMemoryAllocation(allocationSize, memoryProperties));
|
||||
const auto bogusPtr = reinterpret_cast<void *>(0x1);
|
||||
EXPECT_FALSE(usmMemAllocPool.freeSVMAlloc(bogusPtr, true));
|
||||
@@ -235,3 +267,346 @@ TEST_F(InitializationFailedUnifiedMemoryPoolingTest, givenNotInitializedPoolWhen
|
||||
EXPECT_EQ(nullptr, usmMemAllocPool.getPooledAllocationBasePtr(bogusPtr));
|
||||
EXPECT_EQ(0u, usmMemAllocPool.getOffsetInPool(bogusPtr));
|
||||
}
|
||||
|
||||
using UnifiedMemoryPoolingManagerStaticTest = ::testing::Test;
|
||||
TEST_F(UnifiedMemoryPoolingManagerStaticTest, givenUsmMemAllocPoolsManagerWhenCallingCanBePooledThenCorrectValueIsReturned) {
|
||||
const RootDeviceIndicesContainer rootDeviceIndices;
|
||||
const std::map<uint32_t, DeviceBitfield> deviceBitfields;
|
||||
SVMAllocsManager::UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::hostUnifiedMemory, MemoryConstants::pageSize2M, rootDeviceIndices, deviceBitfields);
|
||||
EXPECT_TRUE(MockUsmMemAllocPoolsManager::canBePooled(UsmMemAllocPoolsManager::maxPoolableSize, unifiedMemoryProperties));
|
||||
EXPECT_FALSE(MockUsmMemAllocPoolsManager::canBePooled(UsmMemAllocPoolsManager::maxPoolableSize + 1, unifiedMemoryProperties));
|
||||
|
||||
unifiedMemoryProperties.alignment = UsmMemAllocPool::chunkAlignment / 2;
|
||||
EXPECT_FALSE(MockUsmMemAllocPoolsManager::canBePooled(UsmMemAllocPoolsManager::maxPoolableSize, unifiedMemoryProperties));
|
||||
|
||||
unifiedMemoryProperties.alignment = UsmMemAllocPool::chunkAlignment;
|
||||
unifiedMemoryProperties.allocationFlags.allFlags = 1u;
|
||||
EXPECT_FALSE(MockUsmMemAllocPoolsManager::canBePooled(UsmMemAllocPoolsManager::maxPoolableSize, unifiedMemoryProperties));
|
||||
|
||||
unifiedMemoryProperties.allocationFlags.allFlags = 0u;
|
||||
unifiedMemoryProperties.allocationFlags.allAllocFlags = 1u;
|
||||
EXPECT_FALSE(MockUsmMemAllocPoolsManager::canBePooled(UsmMemAllocPoolsManager::maxPoolableSize, unifiedMemoryProperties));
|
||||
}
|
||||
|
||||
class UnifiedMemoryPoolingManagerTest : public SVMMemoryAllocatorFixture<true>, public ::testing::TestWithParam<std::tuple<InternalMemoryType, bool>> {
|
||||
public:
|
||||
void SetUp() override {
|
||||
REQUIRE_64BIT_OR_SKIP();
|
||||
SVMMemoryAllocatorFixture::setUp();
|
||||
poolMemoryType = std::get<0>(GetParam());
|
||||
failAllocation = std::get<1>(GetParam());
|
||||
|
||||
deviceFactory = std::unique_ptr<UltDeviceFactory>(new UltDeviceFactory(1, 1));
|
||||
device = deviceFactory->rootDevices[0];
|
||||
|
||||
RootDeviceIndicesContainer rootDeviceIndicesPool;
|
||||
rootDeviceIndicesPool.pushUnique(device->getRootDeviceIndex());
|
||||
std::map<uint32_t, DeviceBitfield> deviceBitfieldsPool;
|
||||
deviceBitfieldsPool.emplace(device->getRootDeviceIndex(), device->getDeviceBitfield());
|
||||
usmMemAllocPoolsManager.reset(new MockUsmMemAllocPoolsManager(device->getMemoryManager(),
|
||||
rootDeviceIndicesPool,
|
||||
deviceBitfieldsPool,
|
||||
device,
|
||||
poolMemoryType));
|
||||
ASSERT_NE(nullptr, usmMemAllocPoolsManager);
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->isInitialized());
|
||||
poolInfo0To4Kb = usmMemAllocPoolsManager->poolInfos[0];
|
||||
poolInfo4KbTo64Kb = usmMemAllocPoolsManager->poolInfos[1];
|
||||
poolInfo64KbTo2Mb = usmMemAllocPoolsManager->poolInfos[2];
|
||||
poolInfo2MbTo16Mb = usmMemAllocPoolsManager->poolInfos[3];
|
||||
poolInfo16MbTo64Mb = usmMemAllocPoolsManager->poolInfos[4];
|
||||
poolInfo64MbTo256Mb = usmMemAllocPoolsManager->poolInfos[5];
|
||||
svmManager = std::make_unique<MockSVMAllocsManager>(device->getMemoryManager(), false);
|
||||
mockMemoryManager = static_cast<MockMemoryManager *>(device->getMemoryManager());
|
||||
mockMemoryManager->failInDevicePoolWithError = failAllocation;
|
||||
if (InternalMemoryType::deviceUnifiedMemory == poolMemoryType) {
|
||||
mockMemoryManager->localMemorySupported[mockRootDeviceIndex] = true;
|
||||
}
|
||||
|
||||
poolMemoryProperties = std::make_unique<SVMAllocsManager::UnifiedMemoryProperties>(poolMemoryType, MemoryConstants::pageSize2M, rootDeviceIndices, deviceBitfields);
|
||||
poolMemoryProperties->device = poolMemoryType == InternalMemoryType::deviceUnifiedMemory ? device : nullptr;
|
||||
}
|
||||
void TearDown() override {
|
||||
SVMMemoryAllocatorFixture::tearDown();
|
||||
}
|
||||
|
||||
void *createAlloc(size_t size, SVMAllocsManager::UnifiedMemoryProperties &unifiedMemoryProperties) {
|
||||
void *ptr = nullptr;
|
||||
auto mockGa = std::make_unique<MockGraphicsAllocation>(mockRootDeviceIndex, nullptr, size);
|
||||
mockGa->gpuAddress = nextMockGraphicsAddress;
|
||||
mockGa->cpuPtr = reinterpret_cast<void *>(nextMockGraphicsAddress);
|
||||
if (InternalMemoryType::deviceUnifiedMemory == poolMemoryType) {
|
||||
mockGa->setAllocationType(AllocationType::svmGpu);
|
||||
mockMemoryManager->mockGa = mockGa.release();
|
||||
mockMemoryManager->returnMockGAFromDevicePool = true;
|
||||
ptr = svmManager->createUnifiedMemoryAllocation(size, unifiedMemoryProperties);
|
||||
mockMemoryManager->returnMockGAFromDevicePool = false;
|
||||
}
|
||||
if (InternalMemoryType::hostUnifiedMemory == poolMemoryType) {
|
||||
mockGa->setAllocationType(AllocationType::svmCpu);
|
||||
mockMemoryManager->mockGa = mockGa.release();
|
||||
mockMemoryManager->returnMockGAFromHostPool = true;
|
||||
ptr = svmManager->createHostUnifiedMemoryAllocation(size, unifiedMemoryProperties);
|
||||
mockMemoryManager->returnMockGAFromHostPool = false;
|
||||
}
|
||||
EXPECT_NE(nullptr, ptr);
|
||||
nextMockGraphicsAddress = alignUp(nextMockGraphicsAddress + size + 1, MemoryConstants::pageSize2M);
|
||||
return ptr;
|
||||
}
|
||||
const size_t poolSize = 2 * MemoryConstants::megaByte;
|
||||
std::unique_ptr<MockUsmMemAllocPoolsManager> usmMemAllocPoolsManager;
|
||||
std::unique_ptr<UltDeviceFactory> deviceFactory;
|
||||
Device *device;
|
||||
std::unique_ptr<MockSVMAllocsManager> svmManager;
|
||||
std::unique_ptr<SVMAllocsManager::UnifiedMemoryProperties> poolMemoryProperties;
|
||||
MockMemoryManager *mockMemoryManager;
|
||||
InternalMemoryType poolMemoryType;
|
||||
bool failAllocation;
|
||||
uint64_t nextMockGraphicsAddress = alignUp(std::numeric_limits<uint64_t>::max() - MemoryConstants::teraByte, MemoryConstants::pageSize2M);
|
||||
UsmMemAllocPoolsManager::PoolInfo poolInfo0To4Kb;
|
||||
UsmMemAllocPoolsManager::PoolInfo poolInfo4KbTo64Kb;
|
||||
UsmMemAllocPoolsManager::PoolInfo poolInfo64KbTo2Mb;
|
||||
UsmMemAllocPoolsManager::PoolInfo poolInfo2MbTo16Mb;
|
||||
UsmMemAllocPoolsManager::PoolInfo poolInfo16MbTo64Mb;
|
||||
UsmMemAllocPoolsManager::PoolInfo poolInfo64MbTo256Mb;
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
UnifiedMemoryPoolingManagerTestParameterized,
|
||||
UnifiedMemoryPoolingManagerTest,
|
||||
::testing::Combine(
|
||||
::testing::Values(InternalMemoryType::deviceUnifiedMemory, InternalMemoryType::hostUnifiedMemory),
|
||||
::testing::Values(false)));
|
||||
|
||||
TEST_P(UnifiedMemoryPoolingManagerTest, givenNotInitializedPoolsManagerWhenUsingPoolThenMethodsSucceed) {
|
||||
void *ptr = reinterpret_cast<void *>(0x1u);
|
||||
const void *constPtr = const_cast<const void *>(ptr);
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->freeSVMAlloc(constPtr, true));
|
||||
EXPECT_EQ(nullptr, usmMemAllocPoolsManager->getPooledAllocationBasePtr(constPtr));
|
||||
EXPECT_EQ(0u, usmMemAllocPoolsManager->getPooledAllocationSize(constPtr));
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->recycleSVMAlloc(ptr, true));
|
||||
EXPECT_EQ(0u, usmMemAllocPoolsManager->getOffsetInPool(constPtr));
|
||||
EXPECT_EQ(nullptr, usmMemAllocPoolsManager->getPoolContainingAlloc(constPtr));
|
||||
usmMemAllocPoolsManager->trim();
|
||||
|
||||
auto mockDevice = reinterpret_cast<MockDevice *>(usmMemAllocPoolsManager->device);
|
||||
usmMemAllocPoolsManager->callBaseGetFreeMemory = true;
|
||||
mockDevice->deviceInfo.localMemSize = 4 * MemoryConstants::gigaByte;
|
||||
mockDevice->deviceInfo.globalMemSize = 8 * MemoryConstants::gigaByte;
|
||||
mockMemoryManager->localMemAllocsSize[mockDevice->getRootDeviceIndex()].store(1 * MemoryConstants::gigaByte);
|
||||
auto mutableHwInfo = mockDevice->getRootDeviceEnvironment().getMutableHardwareInfo();
|
||||
EXPECT_EQ(mutableHwInfo, &mockDevice->getHardwareInfo());
|
||||
mutableHwInfo->capabilityTable.isIntegratedDevice = false;
|
||||
EXPECT_EQ(3 * MemoryConstants::gigaByte, usmMemAllocPoolsManager->getFreeMemory());
|
||||
|
||||
mutableHwInfo->capabilityTable.isIntegratedDevice = true;
|
||||
EXPECT_EQ(7 * MemoryConstants::gigaByte, usmMemAllocPoolsManager->getFreeMemory());
|
||||
|
||||
usmMemAllocPoolsManager->cleanup();
|
||||
}
|
||||
|
||||
TEST_P(UnifiedMemoryPoolingManagerTest, givenInitializationFailsForOneOfTheSmallPoolsWhenInitializingPoolsManagerThenPoolsAreCleanedUp) {
|
||||
mockMemoryManager->maxSuccessAllocatedGraphicsMemoryIndex = mockMemoryManager->successAllocatedGraphicsMemoryIndex + 2;
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->ensureInitialized(svmManager.get()));
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->isInitialized());
|
||||
ASSERT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo0To4Kb].size());
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->isInitialized());
|
||||
ASSERT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb].size());
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->isInitialized());
|
||||
ASSERT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb].size());
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->isInitialized());
|
||||
}
|
||||
|
||||
TEST_P(UnifiedMemoryPoolingManagerTest, givenInitializedPoolsManagerWhenAllocatingNotGreaterThan2MBThenSmallPoolsAreUsed) {
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->ensureInitialized(svmManager.get()));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->isInitialized());
|
||||
ASSERT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo0To4Kb].size());
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->isInitialized());
|
||||
ASSERT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb].size());
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->isInitialized());
|
||||
ASSERT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb].size());
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->isInitialized());
|
||||
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
|
||||
|
||||
EXPECT_EQ(2 * MemoryConstants::megaByte, usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->getPoolSize());
|
||||
EXPECT_EQ(2 * MemoryConstants::megaByte, usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->getPoolSize());
|
||||
EXPECT_EQ(16 * MemoryConstants::megaByte, usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->getPoolSize());
|
||||
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->isEmpty());
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->isEmpty());
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->isEmpty());
|
||||
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->sizeIsAllowed(1));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->sizeIsAllowed(4 * MemoryConstants::kiloByte));
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->sizeIsAllowed(4 * MemoryConstants::kiloByte + 1));
|
||||
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->sizeIsAllowed(4 * MemoryConstants::kiloByte));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->sizeIsAllowed(4 * MemoryConstants::kiloByte + 1));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->sizeIsAllowed(64 * MemoryConstants::kiloByte));
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->sizeIsAllowed(64 * MemoryConstants::kiloByte + 1));
|
||||
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->sizeIsAllowed(64 * MemoryConstants::kiloByte));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->sizeIsAllowed(64 * MemoryConstants::kiloByte + 1));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->sizeIsAllowed(2 * MemoryConstants::megaByte));
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->sizeIsAllowed(2 * MemoryConstants::megaByte + 1));
|
||||
|
||||
auto firstPoolAlloc1B = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(1u, *poolMemoryProperties.get());
|
||||
EXPECT_NE(nullptr, firstPoolAlloc1B);
|
||||
EXPECT_EQ(firstPoolAlloc1B, usmMemAllocPoolsManager->getPooledAllocationBasePtr(firstPoolAlloc1B));
|
||||
EXPECT_EQ(1u, usmMemAllocPoolsManager->getPooledAllocationSize(firstPoolAlloc1B));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->isInPool(firstPoolAlloc1B));
|
||||
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(firstPoolAlloc1B, true));
|
||||
|
||||
auto firstPoolAlloc4KB = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(4 * MemoryConstants::kiloByte, *poolMemoryProperties.get());
|
||||
EXPECT_NE(nullptr, firstPoolAlloc4KB);
|
||||
EXPECT_EQ(firstPoolAlloc4KB, usmMemAllocPoolsManager->getPooledAllocationBasePtr(firstPoolAlloc4KB));
|
||||
EXPECT_EQ(4 * MemoryConstants::kiloByte, usmMemAllocPoolsManager->getPooledAllocationSize(firstPoolAlloc4KB));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->isInPool(firstPoolAlloc4KB));
|
||||
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(firstPoolAlloc4KB, true));
|
||||
|
||||
auto secondPoolAlloc4KB1B = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(4 * MemoryConstants::kiloByte + 1, *poolMemoryProperties.get());
|
||||
EXPECT_NE(nullptr, secondPoolAlloc4KB1B);
|
||||
EXPECT_EQ(secondPoolAlloc4KB1B, usmMemAllocPoolsManager->getPooledAllocationBasePtr(secondPoolAlloc4KB1B));
|
||||
EXPECT_EQ(4 * MemoryConstants::kiloByte + 1, usmMemAllocPoolsManager->getPooledAllocationSize(secondPoolAlloc4KB1B));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->isInPool(secondPoolAlloc4KB1B));
|
||||
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(secondPoolAlloc4KB1B, true));
|
||||
|
||||
auto secondPoolAlloc64KB = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(64 * MemoryConstants::kiloByte, *poolMemoryProperties.get());
|
||||
EXPECT_NE(nullptr, secondPoolAlloc64KB);
|
||||
EXPECT_EQ(secondPoolAlloc64KB, usmMemAllocPoolsManager->getPooledAllocationBasePtr(secondPoolAlloc64KB));
|
||||
EXPECT_EQ(64 * MemoryConstants::kiloByte, usmMemAllocPoolsManager->getPooledAllocationSize(secondPoolAlloc64KB));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->isInPool(secondPoolAlloc64KB));
|
||||
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(secondPoolAlloc64KB, true));
|
||||
|
||||
auto thirdPoolAlloc64KB1B = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(64 * MemoryConstants::kiloByte + 1, *poolMemoryProperties.get());
|
||||
EXPECT_NE(nullptr, thirdPoolAlloc64KB1B);
|
||||
EXPECT_EQ(thirdPoolAlloc64KB1B, usmMemAllocPoolsManager->getPooledAllocationBasePtr(thirdPoolAlloc64KB1B));
|
||||
EXPECT_EQ(64 * MemoryConstants::kiloByte + 1, usmMemAllocPoolsManager->getPooledAllocationSize(thirdPoolAlloc64KB1B));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->isInPool(thirdPoolAlloc64KB1B));
|
||||
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(thirdPoolAlloc64KB1B, true));
|
||||
|
||||
auto thirdPoolAlloc2MB = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(2 * MemoryConstants::megaByte, *poolMemoryProperties.get());
|
||||
EXPECT_NE(nullptr, thirdPoolAlloc2MB);
|
||||
EXPECT_EQ(thirdPoolAlloc2MB, usmMemAllocPoolsManager->getPooledAllocationBasePtr(thirdPoolAlloc2MB));
|
||||
EXPECT_EQ(2 * MemoryConstants::megaByte, usmMemAllocPoolsManager->getPooledAllocationSize(thirdPoolAlloc2MB));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->isInPool(thirdPoolAlloc2MB));
|
||||
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
|
||||
|
||||
for (auto i = 0u; i < 7; ++i) { // use all memory in third pool
|
||||
auto ptr = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(2 * MemoryConstants::megaByte, *poolMemoryProperties.get());
|
||||
if (nullptr == ptr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto thirdPoolAlloc2MBOverCapacity = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(2 * MemoryConstants::megaByte, *poolMemoryProperties.get());
|
||||
EXPECT_EQ(nullptr, thirdPoolAlloc2MBOverCapacity);
|
||||
|
||||
usmMemAllocPoolsManager->cleanup();
|
||||
}
|
||||
|
||||
TEST_P(UnifiedMemoryPoolingManagerTest, givenInitializedPoolsManagerWhenAllocatingGreaterThan2MBAndNotGreaterThan256BMThenBigPoolsAreUsed) {
|
||||
void *ptr = reinterpret_cast<void *>(0x1u);
|
||||
const void *constPtr = const_cast<const void *>(ptr);
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->ensureInitialized(svmManager.get()));
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->isInitialized());
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->ensureInitialized(svmManager.get()));
|
||||
|
||||
EXPECT_EQ(0u, usmMemAllocPoolsManager->pools[poolInfo2MbTo16Mb].size());
|
||||
EXPECT_EQ(0u, usmMemAllocPoolsManager->pools[poolInfo16MbTo64Mb].size());
|
||||
EXPECT_EQ(0u, usmMemAllocPoolsManager->pools[poolInfo64MbTo256Mb].size());
|
||||
poolMemoryProperties->alignment = UsmMemAllocPool::chunkAlignment;
|
||||
const auto allocSize = 14 * MemoryConstants::megaByte;
|
||||
auto normalAlloc = createAlloc(allocSize, *poolMemoryProperties.get());
|
||||
EXPECT_NE(nullptr, normalAlloc);
|
||||
|
||||
size_t freeMemoryThreshold = static_cast<size_t>((allocSize + usmMemAllocPoolsManager->totalSize) / UsmMemAllocPool::getPercentOfFreeMemoryForRecycling(poolMemoryType));
|
||||
const auto toleranceForFloatingPointArithmetic = static_cast<size_t>(1 / UsmMemAllocPool::getPercentOfFreeMemoryForRecycling(poolMemoryType));
|
||||
usmMemAllocPoolsManager->mockFreeMemory = freeMemoryThreshold - toleranceForFloatingPointArithmetic;
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->recycleSVMAlloc(normalAlloc, true));
|
||||
EXPECT_EQ(0u, usmMemAllocPoolsManager->pools[poolInfo2MbTo16Mb].size());
|
||||
|
||||
const auto totalSizeStart = usmMemAllocPoolsManager->totalSize;
|
||||
usmMemAllocPoolsManager->mockFreeMemory = freeMemoryThreshold + toleranceForFloatingPointArithmetic;
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->recycleSVMAlloc(normalAlloc, true));
|
||||
EXPECT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo2MbTo16Mb].size());
|
||||
EXPECT_EQ(totalSizeStart + allocSize, usmMemAllocPoolsManager->totalSize);
|
||||
auto firstPool = reinterpret_cast<MockUsmMemAllocPool *>(usmMemAllocPoolsManager->pools[poolInfo2MbTo16Mb][0].get());
|
||||
EXPECT_EQ(2 * MemoryConstants::megaByte + 1, firstPool->minServicedSize);
|
||||
EXPECT_EQ(allocSize, firstPool->maxServicedSize);
|
||||
|
||||
auto poolAlloc8MB = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(8 * MemoryConstants::megaByte, *poolMemoryProperties.get());
|
||||
EXPECT_NE(nullptr, poolAlloc8MB);
|
||||
EXPECT_TRUE(firstPool->isInPool(poolAlloc8MB));
|
||||
EXPECT_EQ(8 * MemoryConstants::megaByte, usmMemAllocPoolsManager->getPooledAllocationSize(poolAlloc8MB));
|
||||
EXPECT_EQ(poolAlloc8MB, usmMemAllocPoolsManager->getPooledAllocationBasePtr(poolAlloc8MB));
|
||||
EXPECT_EQ(firstPool->getOffsetInPool(poolAlloc8MB), usmMemAllocPoolsManager->getOffsetInPool(poolAlloc8MB));
|
||||
|
||||
auto allocationNotFitInPool = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(8 * MemoryConstants::megaByte, *poolMemoryProperties.get());
|
||||
EXPECT_EQ(nullptr, allocationNotFitInPool);
|
||||
|
||||
auto alloc64MB = createAlloc(64 * MemoryConstants::megaByte, *poolMemoryProperties.get());
|
||||
freeMemoryThreshold = static_cast<size_t>((64 * MemoryConstants::megaByte + usmMemAllocPoolsManager->totalSize) / UsmMemAllocPool::getPercentOfFreeMemoryForRecycling(poolMemoryType));
|
||||
usmMemAllocPoolsManager->mockFreeMemory = freeMemoryThreshold + toleranceForFloatingPointArithmetic;
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->recycleSVMAlloc(alloc64MB, true));
|
||||
auto poolAlloc64MB = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(64 * MemoryConstants::megaByte, *poolMemoryProperties.get());
|
||||
EXPECT_NE(nullptr, poolAlloc64MB);
|
||||
auto secondPool = reinterpret_cast<MockUsmMemAllocPool *>(usmMemAllocPoolsManager->pools[poolInfo16MbTo64Mb][0].get());
|
||||
EXPECT_TRUE(secondPool->isInPool(poolAlloc64MB));
|
||||
EXPECT_EQ(64 * MemoryConstants::megaByte, usmMemAllocPoolsManager->getPooledAllocationSize(poolAlloc64MB));
|
||||
EXPECT_EQ(poolAlloc64MB, usmMemAllocPoolsManager->getPooledAllocationBasePtr(poolAlloc64MB));
|
||||
allocationNotFitInPool = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(64 * MemoryConstants::megaByte, *poolMemoryProperties.get());
|
||||
EXPECT_EQ(nullptr, allocationNotFitInPool);
|
||||
EXPECT_EQ(nullptr, usmMemAllocPoolsManager->getPoolContainingAlloc(constPtr));
|
||||
|
||||
auto alloc256MB = createAlloc(256 * MemoryConstants::megaByte, *poolMemoryProperties.get());
|
||||
freeMemoryThreshold = static_cast<size_t>((256 * MemoryConstants::megaByte + usmMemAllocPoolsManager->totalSize) / UsmMemAllocPool::getPercentOfFreeMemoryForRecycling(poolMemoryType));
|
||||
usmMemAllocPoolsManager->mockFreeMemory = freeMemoryThreshold + toleranceForFloatingPointArithmetic;
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->recycleSVMAlloc(alloc256MB, true));
|
||||
auto poolAlloc256MB = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(256 * MemoryConstants::megaByte, *poolMemoryProperties.get());
|
||||
EXPECT_NE(nullptr, poolAlloc256MB);
|
||||
auto thirdPool = reinterpret_cast<MockUsmMemAllocPool *>(usmMemAllocPoolsManager->pools[poolInfo64MbTo256Mb][0].get());
|
||||
EXPECT_TRUE(thirdPool->isInPool(poolAlloc256MB));
|
||||
EXPECT_EQ(256 * MemoryConstants::megaByte, usmMemAllocPoolsManager->getPooledAllocationSize(poolAlloc256MB));
|
||||
EXPECT_EQ(poolAlloc256MB, usmMemAllocPoolsManager->getPooledAllocationBasePtr(poolAlloc256MB));
|
||||
allocationNotFitInPool = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(256 * MemoryConstants::megaByte, *poolMemoryProperties.get());
|
||||
EXPECT_EQ(nullptr, allocationNotFitInPool);
|
||||
|
||||
auto alloc256MBForTrim = createAlloc(256 * MemoryConstants::megaByte, *poolMemoryProperties.get());
|
||||
freeMemoryThreshold = static_cast<size_t>((256 * MemoryConstants::megaByte + usmMemAllocPoolsManager->totalSize) / UsmMemAllocPool::getPercentOfFreeMemoryForRecycling(poolMemoryType));
|
||||
usmMemAllocPoolsManager->mockFreeMemory = freeMemoryThreshold + toleranceForFloatingPointArithmetic;
|
||||
EXPECT_TRUE(usmMemAllocPoolsManager->recycleSVMAlloc(alloc256MBForTrim, true));
|
||||
EXPECT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo2MbTo16Mb].size());
|
||||
EXPECT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo16MbTo64Mb].size());
|
||||
EXPECT_EQ(2u, usmMemAllocPoolsManager->pools[poolInfo64MbTo256Mb].size());
|
||||
usmMemAllocPoolsManager->trim();
|
||||
EXPECT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo2MbTo16Mb].size());
|
||||
EXPECT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo16MbTo64Mb].size());
|
||||
EXPECT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo64MbTo256Mb].size());
|
||||
|
||||
auto smallAlloc = createAlloc(2 * MemoryConstants::megaByte - 1, *poolMemoryProperties.get());
|
||||
EXPECT_NE(nullptr, smallAlloc);
|
||||
freeMemoryThreshold = static_cast<size_t>((2 * MemoryConstants::megaByte + usmMemAllocPoolsManager->totalSize) / UsmMemAllocPool::getPercentOfFreeMemoryForRecycling(poolMemoryType));
|
||||
usmMemAllocPoolsManager->mockFreeMemory = freeMemoryThreshold + toleranceForFloatingPointArithmetic;
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->recycleSVMAlloc(smallAlloc, true));
|
||||
|
||||
auto bigAlloc = createAlloc(256 * MemoryConstants::megaByte + 1, *poolMemoryProperties.get());
|
||||
EXPECT_NE(nullptr, bigAlloc);
|
||||
freeMemoryThreshold = static_cast<size_t>((256 * MemoryConstants::megaByte + 1 + usmMemAllocPoolsManager->totalSize) / UsmMemAllocPool::getPercentOfFreeMemoryForRecycling(poolMemoryType));
|
||||
usmMemAllocPoolsManager->mockFreeMemory = freeMemoryThreshold + toleranceForFloatingPointArithmetic;
|
||||
EXPECT_FALSE(usmMemAllocPoolsManager->recycleSVMAlloc(bigAlloc, true));
|
||||
|
||||
svmManager->freeSVMAlloc(smallAlloc);
|
||||
svmManager->freeSVMAlloc(bigAlloc);
|
||||
|
||||
auto allocationOverMaxSize = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(256 * MemoryConstants::megaByte + 1, *poolMemoryProperties.get());
|
||||
EXPECT_EQ(nullptr, allocationOverMaxSize);
|
||||
|
||||
EXPECT_EQ(nullptr, usmMemAllocPoolsManager->getPoolContainingAlloc(constPtr));
|
||||
usmMemAllocPoolsManager->cleanup();
|
||||
}
|
||||
Reference in New Issue
Block a user