blob: decc540dc61da97a2f2fbd91b6e8afe71ce567b6 [file] [log] [blame]
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <executorch/runtime/core/hierarchical_allocator.h>
#include <executorch/runtime/core/memory_allocator.h>
namespace torch {
namespace executor {
// The memory manager for the executor. It is responsible for keeping
// track of the memory allocation across the lifespan of the executor,
// providing allocators for the following types of objects:
//
// 1. Constants - Constant values in the program. TODO(myuan): we may not
// need it (because the constants are hardcoded in the flatbuffer) but
// we'll account for it for the time being for completeness.
//
// 2. Non-constants - Non-constant values in the program, which may or may not
// be tied to a memory plan.
//
// 3. Runtime structures - Any data needed by the executor itself.
// TODO(myuan): determine whether Delegates need to receive it in the "init"
// method for backends to use directly, or whether memory needs will be
// expressed as an argument to the delegated methods for memory planning to
// account for. Same concerns about dynamic behaviour apply.
// 4. Kernel temporary - This is to provide kernels with a way to create memory,
// without having to request it by adding an extra argument. The extra argument
// approach is fine if/when planning desires to account for such memory, but in
// certain cases a kernel may be fine just leaving this as an implementation
// detail of the kernels itself (but we still want to be able to capture such
// memory allocation).
// In general, this memory manager aims to consolidate all dynamic memory needs
// for program execution. This can allow for heap-less execution (relevant to
// some embedded scenarios), and overall have a tighter control over memory
// utilization. The manager, however, cannot ensure all allocation is accounted
// for since kernel implementations are free to use a separate way to allocate
// memory (e.g. for things like scratch space).
// TODO(myuan): analyze the stack data overhead and lifespan.
class MemoryManager {
public:
MemoryManager(
MemoryAllocator* constant_allocator,
HierarchicalAllocator* non_constant_allocator,
MemoryAllocator* runtime_allocator,
MemoryAllocator* kernel_temporary_allocator)
: constant_allocator_(constant_allocator),
non_constant_allocator_(non_constant_allocator),
runtime_allocator_(runtime_allocator),
kernel_temporary_allocator_(kernel_temporary_allocator) {}
/**
* Returns an allocator for constant values in the program.
*/
const MemoryAllocator* get_constant_allocator() const {
return constant_allocator_;
}
/**
* Returns an hierarchical allocator for non-constant values in the program.
*/
HierarchicalAllocator* get_non_constant_allocator() const {
return non_constant_allocator_;
}
/**
* Returns an allocator to be used for any runtime internal structures
* (i.e. not directly program values).
*/
MemoryAllocator* get_runtime_allocator() const {
return runtime_allocator_;
}
/**
* Returns an allocator that kernel implementations can use to
* create temporary memory (i.e. whose lifespan is a single execution
* of the kernel).
*/
MemoryAllocator* get_kernel_temporary_allocator() const {
return kernel_temporary_allocator_;
}
virtual ~MemoryManager() {}
private:
const MemoryAllocator* constant_allocator_;
HierarchicalAllocator* non_constant_allocator_;
MemoryAllocator* runtime_allocator_;
MemoryAllocator* kernel_temporary_allocator_;
};
} // namespace executor
} // namespace torch