File: isa_pool_allocator.cpp

package info (click to toggle)
intel-compute-runtime 25.35.35096.9-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 79,324 kB
  • sloc: cpp: 926,243; lisp: 3,433; sh: 715; makefile: 162; python: 21
file content (136 lines) | stat: -rw-r--r-- 5,262 bytes parent folder | download
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