HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
allocator.h
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License.
3 
4 #pragma once
5 
6 #include "core/common/common.h"
7 #include "core/framework/allocator_stats.h"
9 #include "ortdevice.h"
10 #include "ortmemoryinfo.h"
11 
12 // This configures the arena based allocator used by ORT
13 // See docs/C_API.md for details on what these mean and how to choose these values
14 struct OrtArenaCfg {
22  : max_mem(max_mem),
23  arena_extend_strategy(arena_extend_strategy),
24  initial_chunk_size_bytes(initial_chunk_size_bytes),
25  max_dead_bytes_per_chunk(max_dead_bytes_per_chunk),
26  initial_growth_chunk_size_bytes(initial_growth_chunk_size_bytes) {}
27 
28  size_t max_mem; // use 0 to allow ORT to choose the default
29  int arena_extend_strategy; // use -1 to allow ORT to choose the default, 0 = kNextPowerOfTwo, 1 = kSameAsRequested
30  int initial_chunk_size_bytes; // use -1 to allow ORT to choose the default
31  int max_dead_bytes_per_chunk; // use -1 to allow ORT to choose the default
32  int initial_growth_chunk_size_bytes; // use -1 to allow ORT to choose the default
33 };
34 
35 namespace onnxruntime {
36 constexpr const char* CPU = "Cpu";
37 constexpr const char* CUDA = "Cuda";
38 constexpr const char* CUDA_PINNED = "CudaPinned";
39 constexpr const char* CANN = "Cann";
40 constexpr const char* CANN_PINNED = "CannPinned";
41 constexpr const char* DML = "DML";
42 constexpr const char* HIP = "Hip";
43 constexpr const char* HIP_PINNED = "HipPinned";
44 constexpr const char* OpenVINO_CPU = "OpenVINO_CPU";
45 constexpr const char* OpenVINO_GPU = "OpenVINO_GPU";
46 
47 constexpr size_t kAllocAlignment = 256;
48 
49 class IAllocator;
50 class Stream;
51 namespace synchronize {
52 class Notification;
53 }
54 using WaitNotificationFn = std::function<void(Stream&, synchronize::Notification&)>;
55 void* AllocateBufferWithOptions(IAllocator& allocator, size_t size, bool use_reserve, Stream* stream, WaitNotificationFn wait_fn);
56 
57 template <typename T>
58 using IAllocatorUniquePtr = std::unique_ptr<T, std::function<void(T*)>>;
59 
60 class IAllocator {
61  public:
62  IAllocator(const OrtMemoryInfo& info) : memory_info_(info) {}
63  virtual ~IAllocator() = default;
64  /**
65  @remarks Use SafeInt when calculating the size of memory to allocate using Alloc.
66  */
67  virtual void* Alloc(size_t size) = 0;
68 
69  virtual void Free(void* p) = 0;
70 
71  // TODO: Find a better name than Reserve() and update in all places.
72  // Reserve() is an interface exposed for an implementation of IAllocator
73  // to optionally implement some allocation logic that by-passes any arena-based
74  // logic that may be housed in the Alloc() implementation.
75  // There are SessionOptions config(s) that allow users to allocate some memory
76  // by-passing arena-based logic.
77  // By default, the base implementation just calls Alloc().
78  virtual void* Reserve(size_t size) { return Alloc(size); }
79 
80  const OrtMemoryInfo& Info() const { return memory_info_; };
81 
82  // Each implementation of IAllocator can override and provide their own implementation
83  virtual void GetStats(AllocatorStats* /*stats*/) { return; }
84 
85  static bool CalcMemSizeForArray(size_t nmemb, size_t size, size_t* out) noexcept {
86  return CalcMemSizeForArrayWithAlignment(nmemb, size, 0, out);
87  }
88 
89  /**
90  * Calculate the memory size for an array. The size is bounds checked using SafeInt.
91  * \tparam alignment must be power of 2
92  * \param nmemb Number of members or elements in the array
93  * \param size Size of each element
94  * \param out Total size required after any alignment is applied
95  * \return true, successful. false, overflow
96  */
97  [[nodiscard]] static bool CalcMemSizeForArrayWithAlignment(size_t nmemb, size_t size, size_t alignment, size_t* out) noexcept;
98 
99  /**
100  * https://cwe.mitre.org/data/definitions/190.html
101  * \param alignment must be power of 2
102  * \param nmemb Number of members or elements in the array
103  * \param size Size of each element
104  * \param out Total size required after any alignment is applied
105  * \return true, successful. false, overflow
106  * \remarks This was the original API and was implemented in the header. Replaced with the above version
107  * implemented in the .cc file so that the SafeInt dependency is internal.
108  */
109  template <size_t alignment>
110  [[nodiscard]] static bool CalcMemSizeForArrayWithAlignment(size_t nmemb, size_t size, size_t* out) noexcept;
111 
112  /**
113  * allocate memory for an array which has nmemb items of data, each size bytes long
114  */
115  void* AllocArray(size_t nmemb, size_t size) {
116  size_t len;
117  if (!CalcMemSizeForArray(nmemb, size, &len))
118  return nullptr;
119  return Alloc(len);
120  }
121 
122  /**
123  * allocate memory for an array which has nmemb items of data, each size bytes long
124  */
125  template <size_t alignment>
126  void* AllocArrayWithAlignment(size_t nmemb, size_t size) {
127  size_t len;
128  if (!CalcMemSizeForArrayWithAlignment(nmemb, size, alignment, &len))
129  return nullptr;
130  return Alloc(len);
131  }
132 
133  /**
134  Create a std::unique_ptr that is allocated and freed by the provided IAllocator.
135  @param allocator The allocator.
136  @param count_or_bytes The exact bytes to allocate if T is void, otherwise the number of elements to allocate.
137  @param use_reserve If true, call Reserve() instead of Alloc() to allocate memory.
138  @param stream Which stream instance allocated chunk will be used with.
139  @param wait_fn If the allocator want to dynamic reuse a chunk from another stream, use this wait_fn to sync on
140  the target stream to make the reuse safe.
141  @returns std::unique_ptr with allocated memory and deleter.
142  */
143  template <typename T>
144  static IAllocatorUniquePtr<T> MakeUniquePtr(std::shared_ptr<IAllocator> allocator, size_t count_or_bytes,
145  bool use_reserve = false,
146  Stream* stream = nullptr, WaitNotificationFn wait_fn = nullptr) {
147  if (allocator == nullptr) return nullptr;
148  // for now limit to fundamental types. we could support others, but to do so either we or the caller
149  // needs to call the dtor for the objects, for buffers allocated on device we don't have destructor
150  // static_assert(std::is_fundamental<T>::value, "Fundamental type required as no destructors are called.");
151 
152  size_t alloc_size = count_or_bytes;
153 
154  // if T is not void, 'count_or_bytes' == number of items so allow for that
155  if constexpr (!std::is_void<T>::value) {
156  // sizeof(void) isn't valid, but the compiler isn't smart enough to ignore that this line isn't
157  // reachable if T is void. use std::conditional to 'use' void* in the sizeof call
158  if (!CalcMemSizeForArray(
159  count_or_bytes, sizeof(typename std::conditional<std::is_void<T>::value, void*, T>::type), &alloc_size)) {
160  return nullptr;
161  }
162  }
163 
164  // allocate
165  T* p = static_cast<T*>(AllocateBufferWithOptions(*allocator, alloc_size, use_reserve, stream, std::move(wait_fn)));
166  return IAllocatorUniquePtr<T>{
167  p,
168  [allocator = std::move(allocator)](T* p) { allocator->Free(p); }};
169  }
170 
171  private:
172  OrtMemoryInfo memory_info_;
173 };
174 
175 template <size_t alignment>
176 bool IAllocator::CalcMemSizeForArrayWithAlignment(size_t nmemb, size_t size, size_t* out) noexcept {
177  return CalcMemSizeForArrayWithAlignment(nmemb, size, alignment, out);
178 }
179 
180 class CPUAllocator : public IAllocator {
181  public:
182  explicit CPUAllocator(const OrtMemoryInfo& memory_info) : IAllocator(memory_info) {}
183 
185 
186  void* Alloc(size_t size) override;
187  void Free(void* p) override;
188 };
189 
190 using AllocatorPtr = std::shared_ptr<IAllocator>;
191 
192 void* AllocatorDefaultAlloc(size_t size);
193 void AllocatorDefaultFree(void* p);
194 } // namespace onnxruntime
GLuint GLuint stream
Definition: glcorearb.h:1832
virtual void Free(void *p)=0
void * AllocatorDefaultAlloc(size_t size)
constexpr const char * OpenVINO_GPU
Definition: allocator.h:45
size_t max_mem
Definition: allocator.h:28
constexpr const char * CPU
Definition: allocator.h:36
virtual void GetStats(AllocatorStats *)
Definition: allocator.h:83
constexpr size_t kAllocAlignment
Definition: allocator.h:47
constexpr const char * CUDA_PINNED
Definition: allocator.h:38
GLsizei const GLfloat * value
Definition: glcorearb.h:824
std::function< void(Stream &, synchronize::Notification &)> WaitNotificationFn
Definition: allocator.h:54
void * AllocateBufferWithOptions(IAllocator &allocator, size_t size, bool use_reserve, Stream *stream, WaitNotificationFn wait_fn)
constexpr const char * CUDA
Definition: allocator.h:37
constexpr const char * HIP_PINNED
Definition: allocator.h:43
const OrtMemoryInfo & Info() const
Definition: allocator.h:80
OrtAllocatorType
constexpr const char * HIP
Definition: allocator.h:42
int initial_growth_chunk_size_bytes
Definition: allocator.h:32
static bool CalcMemSizeForArrayWithAlignment(size_t nmemb, size_t size, size_t alignment, size_t *out) noexcept
int arena_extend_strategy
Definition: allocator.h:29
static IAllocatorUniquePtr< T > MakeUniquePtr(std::shared_ptr< IAllocator > allocator, size_t count_or_bytes, bool use_reserve=false, Stream *stream=nullptr, WaitNotificationFn wait_fn=nullptr)
Definition: allocator.h:144
std::unique_ptr< T, std::function< void(T *)>> IAllocatorUniquePtr
Definition: allocator.h:58
static bool CalcMemSizeForArray(size_t nmemb, size_t size, size_t *out) noexcept
Definition: allocator.h:85
void Free(void *p) override
virtual void * Reserve(size_t size)
Definition: allocator.h:78
void AllocatorDefaultFree(void *p)
constexpr const char * CANN
Definition: allocator.h:39
CPUAllocator(const OrtMemoryInfo &memory_info)
Definition: allocator.h:182
void * AllocArray(size_t nmemb, size_t size)
Definition: allocator.h:115
constexpr const char * DML
Definition: allocator.h:41
GLsizeiptr size
Definition: glcorearb.h:664
std::shared_ptr< IAllocator > AllocatorPtr
Definition: allocator.h:190
int initial_chunk_size_bytes
Definition: allocator.h:30
constexpr const char * CANN_PINNED
Definition: allocator.h:40
void * Alloc(size_t size) override
virtual ~IAllocator()=default
void * AllocArrayWithAlignment(size_t nmemb, size_t size)
Definition: allocator.h:126
int max_dead_bytes_per_chunk
Definition: allocator.h:31
OrtArenaCfg(size_t max_mem, int arena_extend_strategy, int initial_chunk_size_bytes, int max_dead_bytes_per_chunk, int initial_growth_chunk_size_bytes)
Definition: allocator.h:20
IAllocator(const OrtMemoryInfo &info)
Definition: allocator.h:62
type
Definition: core.h:1059
virtual void * Alloc(size_t size)=0
constexpr const char * OpenVINO_CPU
Definition: allocator.h:44