feat(python): add alt decompression memory parameter to interpreter (#3614)

Add alt_decompression_memory_size parameter to the Python interpreter
API. When non-zero, allocates a separate memory region for DECODE
operator outputs and calls SetDecompressionMemory before AllocateTensors.

BUG=part of #3256
This commit is contained in:
Ryan Kuester 2026-07-06 11:38:39 -05:00 committed by GitHub
parent e142972d4f
commit 9664901486
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 38 additions and 7 deletions

View file

@ -33,10 +33,11 @@ PYBIND11_MODULE(_runtime, m) {
.def(py::init([](const py::bytes& data,
const std::vector<std::string>& registerers_by_name,
size_t arena_size, int num_resource_variables,
tflite::InterpreterConfig config) {
return std::unique_ptr<InterpreterWrapper>(
new InterpreterWrapper(data.ptr(), registerers_by_name, arena_size,
num_resource_variables, config));
tflite::InterpreterConfig config,
size_t alt_decompression_memory_size) {
return std::unique_ptr<InterpreterWrapper>(new InterpreterWrapper(
data.ptr(), registerers_by_name, arena_size, num_resource_variables,
config, alt_decompression_memory_size));
}))
.def("PrintAllocations", &InterpreterWrapper::PrintAllocations)
.def("Invoke", &InterpreterWrapper::Invoke)

View file

@ -238,7 +238,14 @@ InterpreterWrapper::~InterpreterWrapper() {
InterpreterWrapper::InterpreterWrapper(
PyObject* model_data, const std::vector<std::string>& registerers_by_name,
size_t arena_size, int num_resource_variables, InterpreterConfig config) {
size_t arena_size, int num_resource_variables, InterpreterConfig config,
size_t alt_decompression_memory_size)
: memory_arena_(new uint8_t[arena_size]),
alt_decompression_memory_(alt_decompression_memory_size > 0
? new uint8_t[alt_decompression_memory_size]
: nullptr),
alt_decompression_region_{alt_decompression_memory_.get(),
alt_decompression_memory_size} {
interpreter_ = nullptr;
// `model_data` is used as a raw pointer beyond the scope of this
@ -266,7 +273,6 @@ InterpreterWrapper::InterpreterWrapper(
"--//:with_compression=true to enable compression support.");
}
memory_arena_ = std::unique_ptr<uint8_t[]>(new uint8_t[arena_size]);
for (const std::string& registerer : registerers_by_name) {
if (!AddCustomOpRegistererByName(registerer.c_str(),
&python_ops_resolver_)) {
@ -296,6 +302,14 @@ InterpreterWrapper::InterpreterWrapper(
interpreter_ = new MicroInterpreter(model, python_ops_resolver_, allocator_,
resource_variables_);
if (alt_decompression_memory_size > 0) {
TfLiteStatus status =
interpreter_->SetDecompressionMemory(&alt_decompression_region_, 1);
if (status != kTfLiteOk) {
ThrowRuntimeError("TFLM failed to set decompression memory");
}
}
TfLiteStatus status = interpreter_->AllocateTensors();
if (status != kTfLiteOk) {
ThrowRuntimeError("TFLM failed to allocate tensors");

View file

@ -19,6 +19,7 @@ limitations under the License.
#include "python/tflite_micro/python_ops_resolver.h"
#include "tensorflow/lite/micro/micro_allocator.h"
#include "tensorflow/lite/micro/micro_context.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/micro/recording_micro_allocator.h"
@ -40,7 +41,8 @@ class InterpreterWrapper {
InterpreterWrapper(
PyObject* model_data, const std::vector<std::string>& registerers_by_name,
size_t arena_size, int num_resource_variables,
InterpreterConfig config = InterpreterConfig::kAllocationRecording);
InterpreterConfig config = InterpreterConfig::kAllocationRecording,
size_t alt_decompression_memory_size = 0);
~InterpreterWrapper();
void PrintAllocations();
@ -57,6 +59,8 @@ class InterpreterWrapper {
tflite::RecordingMicroAllocator* recording_allocator_ = nullptr;
const PyObject* model_;
std::unique_ptr<uint8_t[]> memory_arena_;
std::unique_ptr<uint8_t[]> alt_decompression_memory_;
tflite::MicroContext::AlternateMemoryRegion alt_decompression_region_;
tflite::PythonOpsResolver python_ops_resolver_;
tflite::MicroInterpreter* interpreter_;
};

View file

@ -100,6 +100,7 @@ class Interpreter(object):
custom_op_registerers,
arena_size,
intrepreter_config=InterpreterConfig.kAllocationRecording,
alt_decompression_memory_size=0,
):
if model_data is None:
raise ValueError("Model must not be None")
@ -122,6 +123,7 @@ class Interpreter(object):
arena_size,
num_resource_variables,
_ENUM_TRANSLATOR[intrepreter_config],
alt_decompression_memory_size,
)
@classmethod
@ -131,6 +133,7 @@ class Interpreter(object):
custom_op_registerers=[],
arena_size=None,
intrepreter_config=InterpreterConfig.kAllocationRecording,
alt_decompression_memory_size=0,
):
"""Instantiates a TFLM interpreter from a model .tflite filepath.
@ -140,6 +143,9 @@ class Interpreter(object):
custom OP registerer
arena_size: Tensor arena size in bytes. If unused, tensor arena size will
default to 10 times the model size.
alt_decompression_memory_size: Size in bytes of alternate decompression
memory. If non-zero, DECODE operators will use this memory instead of
the main arena for decompressed tensor outputs.
Returns:
An Interpreter instance
@ -155,6 +161,7 @@ class Interpreter(object):
custom_op_registerers,
arena_size,
intrepreter_config,
alt_decompression_memory_size,
)
@classmethod
@ -164,6 +171,7 @@ class Interpreter(object):
custom_op_registerers=[],
arena_size=None,
intrepreter_config=InterpreterConfig.kAllocationRecording,
alt_decompression_memory_size=0,
):
"""Instantiates a TFLM interpreter from a model in byte array.
@ -173,6 +181,9 @@ class Interpreter(object):
custom OP registerer
arena_size: Tensor arena size in bytes. If unused, tensor arena size will
default to 10 times the model size.
alt_decompression_memory_size: Size in bytes of alternate decompression
memory. If non-zero, DECODE operators will use this memory instead of
the main arena for decompressed tensor outputs.
Returns:
An Interpreter instance
@ -183,6 +194,7 @@ class Interpreter(object):
custom_op_registerers,
arena_size,
intrepreter_config,
alt_decompression_memory_size,
)
def print_allocations(self):