Halide 19.0.0
Halide compiler and libraries
Loading...
Searching...
No Matches
memory_resources.h
Go to the documentation of this file.
1#ifndef HALIDE_RUNTIME_MEMORY_RESOURCES_H
2#define HALIDE_RUNTIME_MEMORY_RESOURCES_H
3
4#include "../HalideRuntime.h"
5
6namespace Halide {
7namespace Runtime {
8namespace Internal {
9
10// --
11
12// Hint for allocation usage indicating whether or not the resource
13// is in use, available, or dedicated (and can't be split or shared)
14enum class AllocationStatus {
16 InUse,
20};
21
22// Hint for allocation requests indicating intended usage
23// required between host and device address space mappings
24enum class MemoryVisibility {
25 InvalidVisibility, //< invalid enum value
26 HostOnly, //< host local
27 DeviceOnly, //< device local
28 DeviceToHost, //< transfer from device to host
29 HostToDevice, //< transfer from host to device
30 DefaultVisibility, //< default visibility (use any valid visibility -- unable to determine prior to usage)
31};
32
33// Hint for allocation requests indicating intended update
34// frequency for modifying the contents of the allocation
35enum class MemoryUsage {
36 InvalidUsage, //< invalid enum value
37 StaticStorage, //< intended for static storage, whereby the contents will be set once and remain unchanged
38 DynamicStorage, //< intended for dyanmic storage, whereby the contents will be set frequently and change constantly
39 UniformStorage, //< intended for fast & small fixed read-only uniform storage (intended for passing shader parameters), whereby the contents will be set once and remain unchanged
40 TransferSrc, //< intended for staging storage updates, whereby the contents will be used as the source of a transfer
41 TransferDst, //< intended for staging storage updates, whereby the contents will be used as the destination of a transfer
42 TransferSrcDst, //< intended for staging storage updates, whereby the contents will be used either as a source or destination of a transfer
43 DefaultUsage //< default usage (use any valid usage -- unable to determine prior to usage)
44};
45
46// Hint for allocation requests indicating ideal caching support (if available)
47enum class MemoryCaching {
48 InvalidCaching, //< invalid enum value
49 Cached, //< cached
50 Uncached, //< uncached
51 CachedCoherent, //< cached and coherent
52 UncachedCoherent, //< uncached but still coherent
53 DefaultCaching //< default caching (use any valid caching behaviour -- unable to determine prior to usage)
54};
55
60 size_t alignment = 0; //< required alignment of allocations (zero for no constraint)
61 size_t nearest_multiple = 0; //< require the allocation size to round up to the nearest multiple (zero means no rounding)
62};
63
64// Client-facing struct for exchanging memory block allocation requests
66 void *handle = nullptr; //< client data storing native handle (managed by alloc_block_region/free_block_region)
67 size_t size = 0; //< allocated size (in bytes)
68 bool dedicated = false; //< flag indicating whether allocation is one dedicated resource (or split/shared into other resources)
69 MemoryProperties properties; //< properties for the allocated block
70};
71
72// Client-facing struct for specifying a range of a memory region (eg for crops)
74 size_t head_offset = 0; //< byte offset from start of region
75 size_t tail_offset = 0; //< byte offset from end of region
76};
77
78// Client-facing struct for exchanging memory region allocation requests
80 void *handle = nullptr; //< client data storing native handle (managed by alloc_block_region/free_block_region) or a pointer to region owning allocation
81 size_t offset = 0; //< offset from base address in block (in bytes)
82 size_t size = 0; //< allocated size (in bytes)
83 MemoryRange range; //< optional range (e.g. for handling crops, etc)
84 bool dedicated = false; //< flag indicating whether allocation is one dedicated resource (or split/shared into other resources)
85 bool is_owner = true; //< flag indicating whether allocation is owned by this region, in which case handle is a native handle. Otherwise handle points to owning region of alloction.
86 MemoryProperties properties; //< properties for the allocated region
87};
88
89// Client-facing struct for issuing memory allocation requests
91 size_t offset = 0; //< offset from base address in block (in bytes)
92 size_t size = 0; //< allocated size (in bytes)
93 size_t alignment = 0; //< alignment constraint for address
94 bool dedicated = false; //< flag indicating whether allocation is one dedicated resource (or split/shared into other resources)
95 MemoryProperties properties; //< properties for the allocated region
96};
97
98class RegionAllocator;
99struct BlockRegion;
100
101// Internal struct for block resource state
102// -- Note: first field must MemoryBlock
104 MemoryBlock memory; //< memory info for the allocated block
105 RegionAllocator *allocator = nullptr; //< designated allocator for the block
106 BlockRegion *regions = nullptr; //< head of linked list of memory regions
107 size_t reserved = 0; //< number of bytes already reserved to regions
108};
109
110// Internal struct for block region state
111// -- Note: first field must MemoryRegion
113 MemoryRegion memory; //< memory info for the allocated region
114 uint32_t usage_count = 0; //< number of active clients using region
115 AllocationStatus status = AllocationStatus::InvalidStatus; //< allocation status indicator
116 BlockRegion *next_ptr = nullptr; //< pointer to next block region in linked list
117 BlockRegion *prev_ptr = nullptr; //< pointer to prev block region in linked list
118 BlockResource *block_ptr = nullptr; //< pointer to parent block resource
119};
120
121// Returns true if given byte alignment is a power of two
123 return (x & (x - 1)) == 0;
124}
125
126// Returns an aligned byte offset to adjust the given offset based on alignment constraints
127// -- Alignment must be power of two!
128ALWAYS_INLINE size_t aligned_offset(size_t offset, size_t alignment) {
130 return (alignment == 0) ? (offset) : (offset + (alignment - 1)) & ~(alignment - 1);
131}
132
133// Returns a suitable alignment such that requested alignment is a suitable
134// integer multiple of the required alignment
135ALWAYS_INLINE size_t conform_alignment(size_t requested, size_t required) {
136 size_t alignment = max(requested, required);
137 return ((required > 0) && (alignment > required)) ? (required * ((alignment / required) + 1)) : alignment;
138}
139
140// Returns a padded size to accommodate an adjusted offset due to alignment constraints
141// -- Alignment must be power of two!
142ALWAYS_INLINE size_t aligned_size(size_t offset, size_t size, size_t alignment) {
143 size_t actual_offset = aligned_offset(offset, alignment);
144 size_t padding = actual_offset - offset;
145 size_t actual_size = padding + size;
146 return actual_size;
147}
148
149// Returns a padded size to accommodate an adjusted offset due to alignment constraints rounded up to the nearest multiple
150// -- Alignment must be power of two!
151ALWAYS_INLINE size_t conform_size(size_t offset, size_t size, size_t alignment, size_t nearest_multiple) {
152 size_t adjusted_size = aligned_size(offset, size, alignment);
153 adjusted_size = (alignment > adjusted_size) ? alignment : adjusted_size;
154 if (nearest_multiple > 0) {
155 size_t rounded_size = (((adjusted_size + nearest_multiple - 1) / nearest_multiple) * nearest_multiple);
156 return rounded_size;
157 } else {
158 return adjusted_size;
159 }
160}
161
162// Clamps the given value to be within the [min_value, max_value] range
163ALWAYS_INLINE size_t clamped_size(size_t value, size_t min_value, size_t max_value) {
164 size_t result = (value < min_value) ? min_value : value;
165 return (result > max_value) ? max_value : result;
166}
167
168// Offset the untyped pointer by the given number of bytes
169ALWAYS_INLINE const void *offset_address(const void *address, size_t byte_offset) {
170 const uintptr_t base = reinterpret_cast<uintptr_t>(address);
171 return reinterpret_cast<const void *>(base + byte_offset);
172}
173
174// Offset the untyped pointer by the given number of bytes
175ALWAYS_INLINE void *offset_address(void *address, size_t byte_offset) {
176 const uintptr_t base = reinterpret_cast<uintptr_t>(address);
177 return reinterpret_cast<void *>(base + byte_offset);
178}
179
180// --
181
182typedef void *(*AllocateSystemFn)(void *, size_t);
183typedef void (*DeallocateSystemFn)(void *, void *);
184
185ALWAYS_INLINE void *native_system_malloc(void *user_context, size_t bytes) {
186 return malloc(bytes);
187}
188
189ALWAYS_INLINE void native_system_free(void *user_context, void *ptr) {
190 free(ptr);
191}
192
197
202
203typedef int (*AllocateBlockFn)(void *, MemoryBlock *);
204typedef int (*DeallocateBlockFn)(void *, MemoryBlock *);
205typedef int (*ConformBlockRequestFn)(void *, MemoryRequest *);
206
212
213typedef int (*AllocateRegionFn)(void *, MemoryRegion *);
214typedef int (*DeallocateRegionFn)(void *, MemoryRegion *);
215typedef int (*ConformBlockRegionFn)(void *, MemoryRequest *);
216
222
223// --
224
225} // namespace Internal
226} // namespace Runtime
227} // namespace Halide
228
229// --
230
231extern "C" {
232
233WEAK const char *halide_memory_visibility_name(MemoryVisibility value) {
234 switch (value) {
235 case MemoryVisibility::InvalidVisibility: {
236 return "InvalidVisibility";
237 }
238 case MemoryVisibility::DefaultVisibility: {
239 return "DefaultVisibility";
240 }
241 case MemoryVisibility::HostOnly: {
242 return "HostOnly";
243 }
244 case MemoryVisibility::DeviceOnly: {
245 return "DeviceOnly";
246 }
247 case MemoryVisibility::HostToDevice: {
248 return "HostToDevice";
249 }
250 case MemoryVisibility::DeviceToHost: {
251 return "DeviceToHost";
252 }
253 default: {
254 return "<unknown memory visibility value>";
255 }
256 };
257 return "<unknown memory visibility value>";
258}
259
260WEAK const char *halide_memory_usage_name(MemoryUsage value) {
261 switch (value) {
262 case MemoryUsage::InvalidUsage: {
263 return "InvalidUsage";
264 }
265 case MemoryUsage::DefaultUsage: {
266 return "DefaultUsage";
267 }
268 case MemoryUsage::StaticStorage: {
269 return "StaticStorage";
270 }
271 case MemoryUsage::DynamicStorage: {
272 return "DynamicStorage";
273 }
274 case MemoryUsage::UniformStorage: {
275 return "UniformStorage";
276 }
277 case MemoryUsage::TransferSrc: {
278 return "TransferSrc";
279 }
280 case MemoryUsage::TransferDst: {
281 return "TransferDst";
282 }
283 case MemoryUsage::TransferSrcDst: {
284 return "TransferSrcDst";
285 }
286 default: {
287 return "<unknown memory usage value>";
288 }
289 };
290 return "<unknown memory usage value>";
291}
292
293WEAK const char *halide_memory_caching_name(MemoryCaching value) {
294 switch (value) {
295 case MemoryCaching::InvalidCaching: {
296 return "InvalidCaching";
297 }
298 case MemoryCaching::DefaultCaching: {
299 return "DefaultCaching";
300 }
301 case MemoryCaching::Cached: {
302 return "Cached";
303 }
304 case MemoryCaching::Uncached: {
305 return "Uncached";
306 }
307 case MemoryCaching::CachedCoherent: {
308 return "CachedCoherent";
309 }
310 case MemoryCaching::UncachedCoherent: {
311 return "UncachedCoherent";
312 }
313 default: {
314 return "<unknown memory visibility value>";
315 }
316 };
317 return "<unknown memory visibility value>";
318}
319
320} // extern "C"
321
322// --
323
324#endif // HALIDE_RUNTIME_MEMORY_RESOURCES_H
This file declares the routines used by Halide internally in its runtime.
void * halide_malloc(void *user_context, size_t x)
Halide calls these functions to allocate and free memory.
void halide_free(void *user_context, void *ptr)
Allocator class interface for sub-allocating a contiguous memory block into smaller regions of memory...
WEAK const char * halide_memory_caching_name(MemoryCaching value)
WEAK const char * halide_memory_usage_name(MemoryUsage value)
WEAK const char * halide_memory_visibility_name(MemoryVisibility value)
void *(* AllocateSystemFn)(void *, size_t)
int(* AllocateBlockFn)(void *, MemoryBlock *)
int(* ConformBlockRegionFn)(void *, MemoryRequest *)
int(* ConformBlockRequestFn)(void *, MemoryRequest *)
ALWAYS_INLINE void * native_system_malloc(void *user_context, size_t bytes)
int(* AllocateRegionFn)(void *, MemoryRegion *)
ALWAYS_INLINE size_t conform_alignment(size_t requested, size_t required)
ALWAYS_INLINE bool is_power_of_two_alignment(size_t x)
ALWAYS_INLINE size_t conform_size(size_t offset, size_t size, size_t alignment, size_t nearest_multiple)
ALWAYS_INLINE void native_system_free(void *user_context, void *ptr)
ALWAYS_INLINE size_t clamped_size(size_t value, size_t min_value, size_t max_value)
ALWAYS_INLINE size_t aligned_size(size_t offset, size_t size, size_t alignment)
void(* DeallocateSystemFn)(void *, void *)
int(* DeallocateBlockFn)(void *, MemoryBlock *)
int(* DeallocateRegionFn)(void *, MemoryRegion *)
ALWAYS_INLINE const void * offset_address(const void *address, size_t byte_offset)
ALWAYS_INLINE size_t aligned_offset(size_t offset, size_t alignment)
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
Expr max(const FuncRef &a, const FuncRef &b)
Definition Func.h:600
__UINTPTR_TYPE__ uintptr_t
void * malloc(size_t)
#define ALWAYS_INLINE
__SIZE_TYPE__ size_t
unsigned __INT32_TYPE__ uint32_t
#define halide_abort_if_false(user_context, cond)
#define WEAK
void free(void *)