1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
/*
* Copyright (C) 2024-2025 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/utilities/isa_pool_allocator.h"
#include "shared/source/device/device.h"
#include "shared/source/memory_manager/allocation_properties.h"
#include "shared/source/memory_manager/memory_manager.h"
#include "shared/source/utilities/buffer_pool_allocator.inl"
namespace NEO {
ISAPool::ISAPool(Device *device, bool isBuiltin, size_t storageSize)
: BaseType(device->getMemoryManager(), nullptr), device(device), isBuiltin(isBuiltin) {
auto allocationType = isBuiltin ? NEO::AllocationType::kernelIsaInternal : NEO::AllocationType::kernelIsa;
AllocationProperties allocProperties = {device->getRootDeviceIndex(),
storageSize,
allocationType,
device->getDeviceBitfield()};
allocProperties.isaPaddingIncluded = true;
auto graphicsAllocation = memoryManager->allocateGraphicsMemoryWithProperties(allocProperties);
this->chunkAllocator.reset(new NEO::HeapAllocator(params.startingOffset,
graphicsAllocation ? graphicsAllocation->getUnderlyingBufferSize() : 0u,
MemoryConstants::pageSize,
0u));
this->mainStorage.reset(graphicsAllocation);
this->mtx = std::make_unique<std::mutex>();
this->stackVec.push_back(graphicsAllocation);
}
ISAPool::ISAPool(ISAPool &&pool) noexcept : BaseType(std::move(pool)) {
this->isBuiltin = pool.isBuiltin;
mtx.reset(pool.mtx.release());
this->stackVec = std::move(pool.stackVec);
this->device = pool.device;
}
ISAPool::~ISAPool() {
if (mainStorage) {
device->getMemoryManager()->freeGraphicsMemory(mainStorage.release());
}
}
SharedIsaAllocation *ISAPool::allocateISA(size_t requestedSize) const {
auto offset = static_cast<size_t>(this->chunkAllocator->allocate(requestedSize));
if (offset == 0) {
return nullptr;
}
return new SharedIsaAllocation{this->mainStorage.get(), offset - params.startingOffset, requestedSize, mtx.get()};
}
const StackVec<NEO::GraphicsAllocation *, 1> &ISAPool::getAllocationsVector() {
return stackVec;
}
ISAPoolAllocator::ISAPoolAllocator(Device *device) : device(device) {
}
/**
* @brief This method allocates SharedIsaAllocation object for a single user (module or program).
* In first step, it checks if requested size for the ISA is higher than default pool size
* and creates new ISA pool if it is.
* Next, it tries to allocate using existing pools.
* If failed, all existing pools are drained and performs allocation again.
* If failed, creates another ISA pool and tries to allocate again.
*
* @param[in] isBuiltin flag specifying whether ISA will be used for builtin kernels
* @param[in] size size requested by the client.
*
* @return returns SharedIsaAllocation or nullptr if allocation didn't succeeded
*/
SharedIsaAllocation *ISAPoolAllocator::requestGraphicsAllocationForIsa(bool isBuiltin, size_t sizeWithPadding) {
std::unique_lock lock(allocatorMtx);
auto maxAllocationSize = getAllocationSize(isBuiltin);
if (sizeWithPadding > maxAllocationSize) {
addNewBufferPool(ISAPool(device, isBuiltin, sizeWithPadding));
}
auto sharedIsaAllocation = tryAllocateISA(isBuiltin, sizeWithPadding);
if (sharedIsaAllocation) {
return sharedIsaAllocation;
}
drain();
sharedIsaAllocation = tryAllocateISA(isBuiltin, sizeWithPadding);
if (sharedIsaAllocation) {
return sharedIsaAllocation;
}
addNewBufferPool(ISAPool(device, isBuiltin, getAllocationSize(isBuiltin)));
return tryAllocateISA(isBuiltin, sizeWithPadding);
}
/**
* @brief This method releases SharedIsaAllocation.
*
* @param[in] sharedIsaAllocation SharedIsaAllocation to free.
*
* @note actual chunk is not released immediately, it's freed during drain call.
*/
void ISAPoolAllocator::freeSharedIsaAllocation(SharedIsaAllocation *sharedIsaAllocation) {
std::unique_lock lock(allocatorMtx);
tryFreeFromPoolBuffer(sharedIsaAllocation->getGraphicsAllocation(), sharedIsaAllocation->getOffset(), sharedIsaAllocation->getSize());
delete sharedIsaAllocation;
}
/**
* @brief This method iterates over existing pools and tries to allocate shared isa allocation
* on one of them. It will use only pools with correct isa type.
*
* @param[in] isBuiltin flag specifying whether ISA will be used for builtin kernels
* @param[in] size size requested by the user.
*
* @return returns SharedIsaAllocation or nullptr if allocation didn't succeeded
*/
SharedIsaAllocation *ISAPoolAllocator::tryAllocateISA(bool isBuiltin, size_t size) {
for (auto &isaPoolParent : this->bufferPools) {
auto &isaPool = static_cast<ISAPool &>(isaPoolParent);
if (isaPool.isBuiltinPool() == isBuiltin) {
auto sharedIsaAllocation = isaPool.allocateISA(size);
if (sharedIsaAllocation != nullptr) {
return sharedIsaAllocation;
}
}
}
return nullptr;
}
} // namespace NEO
|