mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-22 10:17:01 +08:00
Refactor buffer pool allocator to support configurable SmallBuffersParams based on product helper capabilities. This patch enables setting custom pool parameters instead of using fixed static values. For devices with 2MB local memory alignment enabled (is2MBLocalMemAlignmentEnabled), use larger pool configuration: - Pool size: 16MB (up from 2MB) - Threshold: 2MB (up from 1MB) - Alignment: 64KB (unchanged) - Starting offset: 64KB (unchanged) This improves memory utilization for devices supporting larger memory alignments while maintaining original parameters for other devices. Key changes: - Moved params from static template to instance member - Added SmallBuffersParams struct with default/large configs - Added constructor and setter methods for params configuration Related-To: NEO-12287 Signed-off-by: Fabian Zwoliński <fabian.zwolinski@intel.com>
128 lines
6.2 KiB
C++
128 lines
6.2 KiB
C++
/*
|
|
* Copyright (C) 2023-2025 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
*/
|
|
|
|
#include "shared/source/memory_manager/memory_manager.h"
|
|
#include "shared/source/os_interface/product_helper.h"
|
|
#include "shared/source/utilities/buffer_pool_allocator.h"
|
|
#include "shared/source/utilities/heap_allocator.h"
|
|
|
|
#include <type_traits>
|
|
|
|
namespace NEO {
|
|
|
|
inline SmallBuffersParams SmallBuffersParams::getPreferredBufferPoolParams(const ProductHelper &productHelper) {
|
|
return productHelper.is2MBLocalMemAlignmentEnabled() ? SmallBuffersParams::getLargePagesParams() : SmallBuffersParams::getDefaultParams();
|
|
}
|
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType>
|
|
AbstractBuffersPool<PoolT, BufferType, BufferParentType>::AbstractBuffersPool(MemoryManager *memoryManager, OnChunkFreeCallback onChunkFreeCb)
|
|
: AbstractBuffersPool<PoolT, BufferType, BufferParentType>::AbstractBuffersPool(memoryManager, onChunkFreeCb, SmallBuffersParams::getDefaultParams()) {}
|
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType>
|
|
AbstractBuffersPool<PoolT, BufferType, BufferParentType>::AbstractBuffersPool(MemoryManager *memoryManager, OnChunkFreeCallback onChunkFreeCb, const SmallBuffersParams ¶ms)
|
|
: memoryManager{memoryManager}, onChunkFreeCallback{onChunkFreeCb}, params{params} {
|
|
static_assert(std::is_base_of_v<BufferParentType, BufferType>);
|
|
}
|
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType>
|
|
AbstractBuffersPool<PoolT, BufferType, BufferParentType>::AbstractBuffersPool(AbstractBuffersPool<PoolT, BufferType, BufferParentType> &&bufferPool)
|
|
: memoryManager{bufferPool.memoryManager},
|
|
mainStorage{std::move(bufferPool.mainStorage)},
|
|
chunkAllocator{std::move(bufferPool.chunkAllocator)},
|
|
onChunkFreeCallback{bufferPool.onChunkFreeCallback},
|
|
params{bufferPool.params} {}
|
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType>
|
|
void AbstractBuffersPool<PoolT, BufferType, BufferParentType>::tryFreeFromPoolBuffer(BufferParentType *possiblePoolBuffer, size_t offset, size_t size) {
|
|
if (this->isPoolBuffer(possiblePoolBuffer)) {
|
|
this->chunksToFree.push_back({offset, size});
|
|
}
|
|
}
|
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType>
|
|
bool AbstractBuffersPool<PoolT, BufferType, BufferParentType>::isPoolBuffer(const BufferParentType *buffer) const {
|
|
static_assert(std::is_base_of_v<BufferParentType, BufferType>);
|
|
|
|
return (buffer && this->mainStorage.get() == buffer);
|
|
}
|
|
|
|
template <typename PoolT, typename BufferType, typename BufferParentType>
|
|
void AbstractBuffersPool<PoolT, BufferType, BufferParentType>::drain() {
|
|
const auto &allocationsVec = this->getAllocationsVector();
|
|
for (auto allocation : allocationsVec) {
|
|
if (allocation && this->memoryManager->allocInUse(*allocation)) {
|
|
return;
|
|
}
|
|
}
|
|
for (auto &chunk : this->chunksToFree) {
|
|
this->chunkAllocator->free(chunk.first + params.startingOffset, chunk.second);
|
|
if (static_cast<PoolT *>(this)->onChunkFreeCallback) {
|
|
(static_cast<PoolT *>(this)->*onChunkFreeCallback)(chunk.first, chunk.second);
|
|
}
|
|
}
|
|
this->chunksToFree.clear();
|
|
}
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::AbstractBuffersAllocator(const SmallBuffersParams ¶ms)
|
|
: params{params} {
|
|
DEBUG_BREAK_IF(params.aggregatedSmallBuffersPoolSize < params.smallBufferThreshold);
|
|
}
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::AbstractBuffersAllocator()
|
|
: AbstractBuffersAllocator(SmallBuffersParams::getDefaultParams()) {}
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
bool AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::isPoolBuffer(const BufferParentType *buffer) const {
|
|
static_assert(std::is_base_of_v<BufferParentType, BufferType>);
|
|
|
|
for (auto &bufferPool : this->bufferPools) {
|
|
if (bufferPool.isPoolBuffer(buffer)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
void AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::tryFreeFromPoolBuffer(BufferParentType *possiblePoolBuffer, size_t offset, size_t size) {
|
|
this->tryFreeFromPoolBuffer(possiblePoolBuffer, offset, size, this->bufferPools);
|
|
}
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
void AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::tryFreeFromPoolBuffer(BufferParentType *possiblePoolBuffer, size_t offset, size_t size, std::vector<BuffersPoolType> &bufferPoolsVec) {
|
|
auto lock = std::unique_lock<std::mutex>(this->mutex);
|
|
for (auto &bufferPool : bufferPoolsVec) {
|
|
bufferPool.tryFreeFromPoolBuffer(possiblePoolBuffer, offset, size); // NOLINT(clang-analyzer-cplusplus.NewDelete)
|
|
}
|
|
}
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
void AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::drain() {
|
|
this->drain(this->bufferPools);
|
|
}
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
void AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::drain(std::vector<BuffersPoolType> &bufferPoolsVec) {
|
|
for (auto &bufferPool : bufferPoolsVec) {
|
|
bufferPool.drain();
|
|
}
|
|
}
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
void AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::addNewBufferPool(BuffersPoolType &&bufferPool) {
|
|
this->addNewBufferPool(std::move(bufferPool), this->bufferPools);
|
|
}
|
|
|
|
template <typename BuffersPoolType, typename BufferType, typename BufferParentType>
|
|
void AbstractBuffersAllocator<BuffersPoolType, BufferType, BufferParentType>::addNewBufferPool(BuffersPoolType &&bufferPool, std::vector<BuffersPoolType> &bufferPoolsVec) {
|
|
if (bufferPool.mainStorage) {
|
|
bufferPoolsVec.push_back(std::move(bufferPool));
|
|
}
|
|
}
|
|
} // namespace NEO
|