1#ifndef HALIDE_RUNTIME_REGION_ALLOCATOR_H
2#define HALIDE_RUNTIME_REGION_ALLOCATOR_H
4#include "../HalideRuntime.h"
52 bool collect(
void *user_context);
53 int release(
void *user_context);
54 int destroy(
void *user_context);
76 bool can_split(
const BlockRegion *region,
size_t size)
const;
82 BlockRegion *create_block_region(
void *user_context,
const MemoryProperties &properties,
size_t offset,
size_t size,
bool dedicated);
85 int destroy_block_region(
void *user_context,
BlockRegion *region);
88 int alloc_block_region(
void *user_context,
BlockRegion *region);
91 int release_block_region(
void *user_context,
BlockRegion *region);
94 int free_block_region(
void *user_context,
BlockRegion *region);
97 bool is_last_block_region(
void *user_context,
const BlockRegion *region)
const;
106 size_t region_count(
void *user_context)
const;
118 if (result ==
nullptr) {
129 instance->
destroy(user_context);
135int RegionAllocator::initialize(
void *user_context,
BlockResource *
mb,
const MemoryAllocators &
ma) {
141 block->
regions = create_block_region(
155#ifdef DEBUG_RUNTIME_INTERNAL
156 debug(user_context) <<
"RegionAllocator: Unable to reserve more memory from block "
165#ifdef DEBUG_RUNTIME_INTERNAL
166 debug(user_context) <<
"RegionAllocator: Failed to locate region for requested size ("
173#ifdef DEBUG_RUNTIME_INTERNAL
174 debug(user_context) <<
"RegionAllocator: Splitting region of size ( " << (
int32_t)(
block_region->memory.size) <<
") "
175 <<
"to accomodate requested size (" << (
int32_t)(
request.size) <<
" bytes)!\n";
191 return release_block_region(user_context,
block_region);
228bool RegionAllocator::is_last_block_region(
void *user_context,
const BlockRegion *region)
const {
229 return ((region ==
nullptr) || (region == region->
next_ptr) || (region->
next_ptr ==
nullptr));
232bool RegionAllocator::is_block_region_suitable_for_request(
void *user_context,
const BlockRegion *region,
const MemoryRequest &
request)
const {
233 if (!is_available(region)) {
234#ifdef DEBUG_RUNTIME_INTERNAL
235 debug(user_context) <<
"RegionAllocator: skipping block region ... not available! "
236 <<
" block_region=" << (
void *)region <<
"\n";
242 if (!is_compatible_block_region(region,
request.properties)) {
243#ifdef DEBUG_RUNTIME_INTERNAL
244 debug(user_context) <<
"RegionAllocator: skipping block region ... incompatible properties! "
245 <<
" block_region=" << (
void *)region <<
"\n";
255#ifdef DEBUG_RUNTIME_INTERNAL
256 debug(user_context) <<
"RegionAllocator: skipping block region ... not enough space for adjusted size! "
257 <<
" block_region=" << (
void *)region <<
"\n";
264#ifdef DEBUG_RUNTIME_INTERNAL
265 debug(user_context) <<
"RegionAllocator: found suitable block region! "
266 <<
" block_region=" << (
void *)region <<
"\n";
274BlockRegion *RegionAllocator::find_block_region(
void *user_context,
const MemoryRequest &
request) {
278#ifdef DEBUG_RUNTIME_INTERNAL
279 debug(user_context) <<
"RegionAllocator: found suitable region ...\n"
280 <<
" user_context=" << (
void *)(user_context) <<
"\n"
281 <<
" block_resource=" << (
void *)block <<
"\n"
285 <<
" requested_is_dedicated=" << (
request.dedicated ?
"true" :
"false") <<
"\n"
301#ifdef DEBUG_RUNTIME_INTERNAL
302 debug(user_context) <<
"RegionAllocator: couldn't find suitable region!\n"
303 <<
" user_context=" << (
void *)(user_context) <<
"\n"
305 <<
" requested_is_dedicated=" << (
request.dedicated ?
"true" :
"false") <<
"\n"
315bool RegionAllocator::is_available(
const BlockRegion *
block_region)
const {
328bool RegionAllocator::can_coalesce(
const BlockRegion *
block_region)
const {
341BlockRegion *RegionAllocator::coalesce_block_regions(
void *user_context, BlockRegion *
block_region) {
344#ifdef DEBUG_RUNTIME_INTERNAL
345 debug(user_context) <<
"Freeing region ("
346 <<
"block_ptr=" << (
void *)
block_region->block_ptr <<
" "
361#ifdef DEBUG_RUNTIME_INTERNAL
362 debug(user_context) <<
"RegionAllocator: Coalescing "
379#ifdef DEBUG_RUNTIME_INTERNAL
380 debug(user_context) <<
"RegionAllocator: Coalescing "
396bool RegionAllocator::can_split(
const BlockRegion *
block_region,
size_t size)
const {
400BlockRegion *RegionAllocator::split_block_region(
void *user_context, BlockRegion *
block_region,
size_t size,
size_t alignment) {
403#ifdef DEBUG_RUNTIME_INTERNAL
404 debug(user_context) <<
"RegionAllocator: Split deallocate region ("
405 <<
"block_ptr=" << (
void *)
block_region->block_ptr <<
" "
422#ifdef DEBUG_RUNTIME_INTERNAL
423 debug(user_context) <<
"RegionAllocator: Conforming size and alignment \n"
424 <<
" requested_size=" << (
uint32_t)size <<
"\n"
426 <<
" requested_alignment=" << (
uint32_t)alignment <<
" "
431#ifdef DEBUG_RUNTIME_INTERNAL
432 debug(user_context) <<
"RegionAllocator: Splitting "
438 BlockRegion *
empty_region = create_block_region(user_context,
454BlockRegion *RegionAllocator::create_block_region(
void *user_context,
const MemoryProperties &properties,
size_t offset,
size_t size,
bool dedicated) {
455#ifdef DEBUG_RUNTIME_INTERNAL
456 debug(user_context) <<
"RegionAllocator: Creating block region ("
457 <<
"user_context=" << (
void *)(user_context) <<
" "
458 <<
"offset=" << (
uint32_t)offset <<
" "
460 <<
"alignment=" << (
uint32_t)properties.alignment <<
" "
461 <<
"dedicated=" << (dedicated ?
"true" :
"false") <<
" "
467 BlockRegion *
block_region =
static_cast<BlockRegion *
>(arena->
reserve(user_context,
true));
469 error(user_context) <<
"RegionAllocator: Failed to allocate new block region!\n";
473#ifdef DEBUG_RUNTIME_INTERNAL
474 debug(user_context) <<
"RegionAllocator: Added block region ("
475 <<
"user_context=" << (
void *)(user_context) <<
" "
476 <<
"block_region=" << (
void *)(
block_region) <<
") ...\n";
492#ifdef DEBUG_RUNTIME_INTERNAL
493 debug(user_context) <<
"Creating region ("
494 <<
"block_ptr=" << (
void *)
block_region->block_ptr <<
" "
503int RegionAllocator::release_block_region(
void *user_context, BlockRegion *
block_region) {
504#ifdef DEBUG_RUNTIME_INTERNAL
505 debug(user_context) <<
"RegionAllocator: Releasing block region ("
506 <<
"user_context=" << (
void *)(user_context) <<
" "
507 <<
"block_region=" << (
void *)(
block_region) <<
") ...\n";
519#ifdef DEBUG_RUNTIME_INTERNAL
520 debug(user_context) <<
"Releasing region ("
521 <<
"block_ptr=" << (
void *)
block_region->block_ptr <<
" "
534int RegionAllocator::destroy_block_region(
void *user_context, BlockRegion *
block_region) {
535#ifdef DEBUG_RUNTIME_INTERNAL
536 debug(user_context) <<
"RegionAllocator: Destroying block region ("
537 <<
"user_context=" << (
void *)(user_context) <<
" "
538 <<
"block_region=" << (
void *)(
block_region) <<
") ...\n";
548int RegionAllocator::alloc_block_region(
void *user_context, BlockRegion *
block_region) {
549#ifdef DEBUG_RUNTIME_INTERNAL
550 debug(user_context) <<
"RegionAllocator: Allocating region (user_context=" << (
void *)(user_context)
562#ifdef DEBUG_RUNTIME_INTERNAL
563 debug(user_context) <<
"Allocating region ("
564 <<
"block_ptr=" << (
void *)
block_region->block_ptr <<
" "
574#ifdef DEBUG_RUNTIME_INTERNAL
575 debug(user_context) <<
"Re-using region ("
576 <<
"block_ptr=" << (
void *)
block_region->block_ptr <<
" "
589int RegionAllocator::free_block_region(
void *user_context, BlockRegion *
block_region) {
590#ifdef DEBUG_RUNTIME_INTERNAL
591 debug(user_context) <<
"RegionAllocator: Freeing block region ("
592 <<
"user_context=" << (
void *)(user_context) <<
" "
598#ifdef DEBUG_RUNTIME_INTERNAL
599 debug(user_context) <<
"Freeing region ("
600 <<
"block_ptr=" << (
void *)
block_region->block_ptr <<
" "
619#ifdef DEBUG_RUNTIME_INTERNAL
620 debug(user_context) <<
"RegionAllocator: Releasing all regions ("
621 <<
"user_context=" << (
void *)(user_context) <<
") ...\n";
636#ifdef DEBUG_RUNTIME_INTERNAL
637 debug(user_context) <<
"RegionAllocator: Collecting free block regions ("
638 <<
"user_context=" << (
void *)(user_context) <<
") ...\n";
642 debug(user_context) <<
" collecting unused regions ("
643 <<
"block_ptr=" << (
void *)block <<
" "
652#ifdef DEBUG_RUNTIME_INTERNAL
654 debug(user_context) <<
" collecting region ("
655 <<
"block_ptr=" << (
void *)
block_region->block_ptr <<
" "
671#ifdef DEBUG_RUNTIME_INTERNAL
672 debug(user_context) <<
" collected unused regions ("
673 <<
"block_ptr=" << (
void *)block <<
" "
674 <<
"region_count=" << (
uint32_t)count <<
" "
683#ifdef DEBUG_RUNTIME_INTERNAL
684 debug(user_context) <<
"RegionAllocator: Destroying all block regions ("
685 <<
"user_context=" << (
void *)(user_context) <<
") ...\n";
728size_t RegionAllocator::region_count(
void *user_context)
const {
729 if (block ==
nullptr) {
733 for (BlockRegion
const *region = block->
regions; !is_last_block_region(user_context, region); region = region->next_ptr) {
void * reserve(void *user_context, bool initialize=false)
static MemoryArena * create(void *user_context, const Config &config, const SystemMemoryAllocatorFns &allocator=default_allocator())
static constexpr uint32_t default_capacity
static void destroy(void *user_context, MemoryArena *arena)
void reclaim(void *user_context, void *ptr)
Allocator class interface for sub-allocating a contiguous memory block into smaller regions of memory...
MemoryRegion * reserve(void *user_context, const MemoryRequest &request)
RegionAllocator & operator=(const RegionAllocator &)=delete
RegionAllocator(const RegionAllocator &)=delete
static int destroy(void *user_context, RegionAllocator *region_allocator)
static RegionAllocator * find_allocator(void *user_context, MemoryRegion *memory_region)
int retain(void *user_context, MemoryRegion *memory_region)
bool collect(void *user_context)
~RegionAllocator()=delete
int reclaim(void *user_context, MemoryRegion *memory_region)
int release(void *user_context, MemoryRegion *memory_region)
BlockResource * block_resource() const
static RegionAllocator * create(void *user_context, BlockResource *block, const MemoryAllocators &ma)
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)
ALWAYS_INLINE size_t conform_alignment(size_t requested, size_t required)
ALWAYS_INLINE size_t conform_size(size_t offset, size_t size, size_t alignment, size_t nearest_multiple)
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 cast(Expr a)
Cast an expression to the halide type corresponding to the C++ type T.
unsigned __INT64_TYPE__ uint64_t
signed __INT32_TYPE__ int32_t
unsigned __INT32_TYPE__ uint32_t
#define halide_abort_if_false(user_context, cond)
RegionAllocator * allocator
MemoryProperties properties
MemoryVisibility visibility
DeallocateRegionFn deallocate
AllocateRegionFn allocate
MemoryRegionAllocatorFns region
SystemMemoryAllocatorFns system
DeallocateSystemFn deallocate
AllocateSystemFn allocate