131 lines
5.2 KiB
C++
131 lines
5.2 KiB
C++
/*
|
|
* Copyright (C) 2023-2024 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
#include "shared/source/helpers/constants.h"
|
|
#include "shared/source/memory_manager/unified_memory_manager.h"
|
|
#include "shared/source/utilities/heap_allocator.h"
|
|
#include "shared/source/utilities/sorted_vector.h"
|
|
|
|
#include <array>
|
|
#include <map>
|
|
|
|
namespace NEO {
|
|
class UsmMemAllocPool {
|
|
public:
|
|
using UnifiedMemoryProperties = SVMAllocsManager::UnifiedMemoryProperties;
|
|
struct AllocationInfo {
|
|
uint64_t address;
|
|
size_t size;
|
|
size_t requestedSize;
|
|
};
|
|
using AllocationsInfoStorage = BaseSortedPointerWithValueVector<AllocationInfo>;
|
|
|
|
UsmMemAllocPool() = default;
|
|
bool initialize(SVMAllocsManager *svmMemoryManager, const UnifiedMemoryProperties &memoryProperties, size_t poolSize, size_t minServicedSize, size_t maxServicedSize);
|
|
bool initialize(SVMAllocsManager *svmMemoryManager, void *ptr, SvmAllocationData *svmData, size_t minServicedSize, size_t maxServicedSize);
|
|
bool isInitialized() const;
|
|
size_t getPoolSize() const;
|
|
void cleanup();
|
|
static bool alignmentIsAllowed(size_t alignment);
|
|
static bool flagsAreAllowed(const UnifiedMemoryProperties &memoryProperties);
|
|
static double getPercentOfFreeMemoryForRecycling(InternalMemoryType memoryType);
|
|
bool sizeIsAllowed(size_t size);
|
|
bool canBePooled(size_t size, const UnifiedMemoryProperties &memoryProperties);
|
|
void *createUnifiedMemoryAllocation(size_t size, const UnifiedMemoryProperties &memoryProperties);
|
|
bool isInPool(const void *ptr) const;
|
|
bool isEmpty();
|
|
bool freeSVMAlloc(const void *ptr, bool blocking);
|
|
size_t getPooledAllocationSize(const void *ptr);
|
|
void *getPooledAllocationBasePtr(const void *ptr);
|
|
size_t getOffsetInPool(const void *ptr) const;
|
|
|
|
static constexpr auto chunkAlignment = 512u;
|
|
|
|
protected:
|
|
size_t poolSize{};
|
|
std::unique_ptr<HeapAllocator> chunkAllocator;
|
|
void *pool{};
|
|
void *poolEnd{};
|
|
SVMAllocsManager *svmMemoryManager{};
|
|
AllocationsInfoStorage allocations;
|
|
std::mutex mtx;
|
|
InternalMemoryType poolMemoryType;
|
|
size_t minServicedSize;
|
|
size_t maxServicedSize;
|
|
};
|
|
|
|
class UsmMemAllocPoolsManager {
|
|
public:
|
|
struct PoolInfo {
|
|
size_t minServicedSize;
|
|
size_t maxServicedSize;
|
|
size_t preallocateSize;
|
|
bool isPreallocated() const;
|
|
bool operator<(const PoolInfo &rhs) const {
|
|
return this->minServicedSize < rhs.minServicedSize;
|
|
}
|
|
};
|
|
// clang-format off
|
|
const std::array<const PoolInfo, 6> poolInfos = {
|
|
PoolInfo{ 0, 4 * KB, 2 * MB},
|
|
PoolInfo{ 4 * KB+1, 64 * KB, 2 * MB},
|
|
PoolInfo{64 * KB+1, 2 * MB, 16 * MB},
|
|
PoolInfo{ 2 * MB+1, 16 * MB, 0},
|
|
PoolInfo{16 * MB+1, 64 * MB, 0},
|
|
PoolInfo{64 * MB+1, 256 * MB, 0}};
|
|
// clang-format on
|
|
const size_t firstNonPreallocatedIndex = 3u;
|
|
|
|
using UnifiedMemoryProperties = SVMAllocsManager::UnifiedMemoryProperties;
|
|
static constexpr uint64_t KB = MemoryConstants::kiloByte; // NOLINT(readability-identifier-naming)
|
|
static constexpr uint64_t MB = MemoryConstants::megaByte; // NOLINT(readability-identifier-naming)
|
|
static constexpr uint64_t maxPoolableSize = 256 * MB;
|
|
UsmMemAllocPoolsManager(MemoryManager *memoryManager,
|
|
const RootDeviceIndicesContainer &rootDeviceIndices,
|
|
const std::map<uint32_t, NEO::DeviceBitfield> &deviceBitFields,
|
|
Device *device,
|
|
InternalMemoryType poolMemoryType) : memoryManager(memoryManager), rootDeviceIndices(rootDeviceIndices), deviceBitFields(deviceBitFields), device(device), poolMemoryType(poolMemoryType){};
|
|
MOCKABLE_VIRTUAL ~UsmMemAllocPoolsManager() = default;
|
|
bool ensureInitialized(SVMAllocsManager *svmMemoryManager);
|
|
bool isInitialized() const;
|
|
void trim();
|
|
void trim(std::vector<std::unique_ptr<UsmMemAllocPool>> &poolVector);
|
|
void cleanup();
|
|
void *createUnifiedMemoryAllocation(size_t size, const UnifiedMemoryProperties &memoryProperties);
|
|
bool freeSVMAlloc(const void *ptr, bool blocking);
|
|
MOCKABLE_VIRTUAL uint64_t getFreeMemory();
|
|
bool recycleSVMAlloc(void *ptr, bool blocking);
|
|
size_t getPooledAllocationSize(const void *ptr);
|
|
void *getPooledAllocationBasePtr(const void *ptr);
|
|
size_t getOffsetInPool(const void *ptr);
|
|
|
|
protected:
|
|
static bool canBePooled(size_t size, const UnifiedMemoryProperties &memoryProperties) {
|
|
return size <= maxPoolableSize &&
|
|
UsmMemAllocPool::alignmentIsAllowed(memoryProperties.alignment) &&
|
|
UsmMemAllocPool::flagsAreAllowed(memoryProperties);
|
|
}
|
|
bool belongsInPreallocatedPool(size_t size) {
|
|
return size <= poolInfos[firstNonPreallocatedIndex - 1].maxServicedSize;
|
|
}
|
|
|
|
UsmMemAllocPool *getPoolContainingAlloc(const void *ptr);
|
|
|
|
SVMAllocsManager *svmMemoryManager{};
|
|
MemoryManager *memoryManager;
|
|
RootDeviceIndicesContainer rootDeviceIndices;
|
|
std::map<uint32_t, NEO::DeviceBitfield> deviceBitFields;
|
|
Device *device;
|
|
InternalMemoryType poolMemoryType;
|
|
size_t totalSize{};
|
|
std::mutex mtx;
|
|
std::map<PoolInfo, std::vector<std::unique_ptr<UsmMemAllocPool>>> pools;
|
|
};
|
|
|
|
} // namespace NEO
|