CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
219 lines
8.1 KiB
C++
219 lines
8.1 KiB
C++
/*
|
|
* Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <functional>
|
|
#include "top.hpp"
|
|
#include "device/device.hpp"
|
|
#include "object.hpp"
|
|
#include "commandqueue.hpp"
|
|
|
|
namespace amd {
|
|
|
|
class HeapBlock;
|
|
class VmHeap;
|
|
class VmHeapArray;
|
|
|
|
class HeapBlock {
|
|
public:
|
|
friend VmHeap;
|
|
//! Constructor
|
|
HeapBlock(VmHeap* owner = nullptr, //!< VmHeap object that owns this heap block
|
|
size_t size = 0, //!< Heap block size for allocation
|
|
size_t offset = 0) //!< Heap block offset
|
|
: owner_(owner), size_(size), offset_(offset), next_(nullptr), prev_(nullptr), busy_(false) {}
|
|
|
|
//! Destructor does some sanity checks
|
|
~HeapBlock() { assert(!busy_ && "The blocked must be destroyed explicitly!"); }
|
|
|
|
//! Gets the offset
|
|
size_t Offset() const { return offset_; }
|
|
|
|
private:
|
|
HeapBlock() = delete;
|
|
HeapBlock(const HeapBlock&) = delete;
|
|
HeapBlock& operator=(const HeapBlock&) = delete;
|
|
|
|
VmHeap* owner_; //!< Heap that owns this block
|
|
size_t size_; //!< Size of the block in bytes
|
|
size_t offset_; //!< Offset of this block in the heap
|
|
HeapBlock* next_; //!< Next block on the list, or nullptr
|
|
HeapBlock* prev_; //!< Previous block on the list, or nullptr
|
|
bool busy_; //!< True if the block is in use
|
|
};
|
|
|
|
class VmHeap {
|
|
public:
|
|
friend VmHeapArray;
|
|
static const size_t kChunkSize = 128 * Mi; //!< Chunk size, must be power of 2
|
|
static const size_t kMinBlockAlignment = 256;
|
|
typedef std::function<amd::HostQueue&()> GetQueueFunc;
|
|
|
|
VmHeap(Device* device, //!< GPU device object
|
|
GetQueueFunc get_queue //!< Function to retrieve a map queue
|
|
)
|
|
: VmHeap(device, device->info().globalMemSize_ / 8, kChunkSize, get_queue) {}
|
|
|
|
VmHeap(Device* device, //!< GPU device object
|
|
size_t va_size, //!< The size of the allocated heap (bytes).Virtual address space
|
|
size_t chunk_size, //!< The size of single chunk for physical memory growth
|
|
GetQueueFunc get_queue //!< Function to retrieve a map/unmap queue
|
|
);
|
|
|
|
//! Heap destructor
|
|
virtual ~VmHeap();
|
|
|
|
//! Returns a pointer to the allocated device memory from a heap
|
|
address Alloc(size_t size //! The allocation size
|
|
);
|
|
|
|
//! Release memory back to the VM heap
|
|
void Free(amd::Memory* memory);
|
|
|
|
//! Unmaps freed memory based on the threshold
|
|
void TrimPhysMemory(size_t unmap_threshold);
|
|
|
|
//! Enable memory unmap threashold (default 0 unmap always)
|
|
void SetUnmapThreshold(uint64_t threshold) { unmap_threshold_ = threshold; }
|
|
|
|
//! Returns mapped memory size (total allocated physical memory)
|
|
uint64_t MappedSize() const { return mapped_size_; }
|
|
|
|
//! Returns mapped memory size (allocated physical memory) without actual allocations
|
|
uint64_t FreeMappedSize() const { return mapped_size_ - (va_size_ - free_size_); }
|
|
|
|
//! Returns true if the address is in the range of this heap
|
|
bool InRange(void* addr) {
|
|
return ((addr >= base_address_) && (addr <= (base_address_ + va_size_))) ? true : false;
|
|
}
|
|
|
|
private:
|
|
VmHeap() = delete;
|
|
VmHeap(const VmHeap&) = delete;
|
|
VmHeap& operator=(const VmHeap&) = delete;
|
|
|
|
//! Ceates heap object. Reserves virtual address range for the heap operation
|
|
bool Create();
|
|
|
|
//! Reseves address range for memory allocations
|
|
address ReserveAddressRange(address start, size_t size, size_t alignment);
|
|
|
|
//! Releases address range specified by the address
|
|
bool ReleaseAddressRange(void* addr);
|
|
|
|
//! Commits actual physical memory on the specified address
|
|
bool CommitMemory(void* addr, size_t size);
|
|
|
|
//! Uncommits physical memory from the spcified address
|
|
bool UncommitMemory(void* addr, size_t size);
|
|
|
|
HeapBlock* AllocBlock(size_t size //! The allocation size
|
|
);
|
|
|
|
//! Release memory back to a heap
|
|
void FreeBlock(HeapBlock* blk);
|
|
|
|
//! Insert a block into a list
|
|
void InsertBlock(HeapBlock** list, HeapBlock* node);
|
|
|
|
//! Merge a block into a list
|
|
void MergeBlock(HeapBlock** list, HeapBlock* node);
|
|
|
|
//! Remove a block from a list
|
|
void DetachBlock(HeapBlock** list, HeapBlock* node);
|
|
|
|
//! Splits a block into two pieces
|
|
HeapBlock* SplitBlock(HeapBlock* node, size_t size);
|
|
|
|
//! Maps physical memory into specified address space
|
|
bool MapPhysMemory(size_t offset, size_t size);
|
|
|
|
//! Unmaps physical memory from the specified address
|
|
void UnmapPhysMemory(size_t offset, size_t size);
|
|
|
|
//! Join two blocks, transferring the size of the second into the first and deleting the second
|
|
void Join2Blocks(HeapBlock* first, HeapBlock* second) const;
|
|
|
|
//! Returns a queue for VM map/unmap operations
|
|
amd::HostQueue& GetVmQueue() const { return get_vm_queue_(); }
|
|
|
|
address base_address_ = nullptr; //!< GPU virtual address base of the heap
|
|
amd::Memory* base_memory_ = nullptr; //!< VA space base object, used in the view creation
|
|
HeapBlock* free_list_ = nullptr; //!< Head block for free list
|
|
HeapBlock* busy_list_ = nullptr; //!< Head block for busy list
|
|
size_t free_size_ = 0; //!< Total free size of the heap (both mapped and unmapped)
|
|
size_t va_size_ = 0; //!< Heap virtual address space size
|
|
size_t block_alignment_ = 1; //!< Size of an allocation page
|
|
size_t chunk_size_ = 0; //!< Chunk size (min physical allocation for the growth)
|
|
uint64_t unmap_threshold_ = 0; //!< Unmap threshold in bytes,used to release phys memory
|
|
uint64_t mapped_size_ = 0; //!< Size of mapped memory
|
|
uint64_t max_mapped_size_ = 0; //!< Max size of mapped memory in this heap
|
|
bool created_ = false; //!< Used for deferred VM heap allocation
|
|
std::recursive_mutex lock_; //!< Lock to serialise heap accesses
|
|
Device* device_; //!< Device that owns this heap
|
|
GetQueueFunc get_vm_queue_; //!< Queue for VM operations
|
|
|
|
std::vector<bool> mapped_mem_; //!< A map of mapped memory, the size is total_size/chunk_size
|
|
};
|
|
|
|
//! Implements an array of vm heaps of different sizes for more efficient management
|
|
class VmHeapArray {
|
|
public:
|
|
VmHeapArray(Device* device, //!< GPU device object
|
|
VmHeap::GetQueueFunc get_queue //!< Function to retrieve a map queue
|
|
)
|
|
: heap0_(device, device->info().globalMemSize_ / 8, VmHeap::kChunkSize, get_queue),
|
|
heap1_(device, device->info().globalMemSize_ / 4, VmHeap::kChunkSize, get_queue),
|
|
heap2_(device, device->info().globalMemSize_ * 5 / 8, VmHeap::kChunkSize, get_queue),
|
|
heap3_(device, device->info().globalMemSize_, VmHeap::kChunkSize, get_queue),
|
|
device_(device) {}
|
|
|
|
//! Returns a pointer to the allocated device memory from a heap
|
|
address Alloc(size_t size //! The allocation size
|
|
);
|
|
|
|
//! Release memory back to the VM heap
|
|
void Free(amd::Memory* memory);
|
|
|
|
//! Unmaps freed memory based on the threshold
|
|
void TrimPhysMemory(size_t unmap_threshold);
|
|
|
|
//! Enable memory unmap threashold (default 0 unmap always)
|
|
void SetUnmapThreshold(uint64_t threshold);
|
|
|
|
//! Returns mapped memory size (total allocated physical memory)
|
|
uint64_t MappedSize() const;
|
|
|
|
//! Returns mapped memory size (allocated physical memory) without actual allocations
|
|
uint64_t FreeMappedSize() const;
|
|
|
|
//! Returns the maximum mapped memory size
|
|
uint64_t MaxMappedSize() const;
|
|
|
|
//! Returns the maximum mapped memory size
|
|
void ResetMaxMappedSize();
|
|
|
|
private:
|
|
VmHeapArray() = delete;
|
|
VmHeapArray(const VmHeapArray&) = delete;
|
|
VmHeapArray& operator=(const VmHeapArray&) = delete;
|
|
|
|
static const uint32_t kMaxArraySize = 4; //!< The number of vm heap in the array
|
|
// @note: gcc10.2 or lower wrongly uses copy constructor in the initialization
|
|
// of VmHeap array of objects. Hence, use an array of VmHeap pointers for now
|
|
VmHeap* vm_heaps_[kMaxArraySize] = {&heap0_, &heap1_, &heap2_, &heap3_}; //!< The array of heaps
|
|
VmHeap heap0_;
|
|
VmHeap heap1_;
|
|
VmHeap heap2_;
|
|
VmHeap heap3_;
|
|
|
|
uint64_t unmap_threshold_ = 0; //!< Unmap threshold in bytes,used to release phys memory
|
|
Device* device_; //!< Device that owns this heap
|
|
};
|
|
|
|
} // namespace amd
|