ESP32 Arduino中dram0_0_seg溢出问题求助
问题描述
使用Espressif ESP-WROVER-KIT(320KB RAM)进行机器学习图像分类任务时,编译代码出现内存溢出错误:
region `dram0_0_seg' overflowed by 10079520 bytes
检查.map文件发现.dram0.data大小为0x9b9abc(约10MB),远超开发板RAM容量。核心代码如下:
#include "model.h" // Include the model header file #include <tensorflow/lite/micro/all_ops_resolver.h> #include <tensorflow/lite/micro/micro_error_reporter.h> #include <tensorflow/lite/micro/micro_interpreter.h> #include <tensorflow/lite/schema/schema_generated.h> #include <tensorflow/lite/version.h> #include <Arduino.h> // Globals, used for compatibility with Arduino-style sketches. namespace { tflite::MicroErrorReporter micro_error_reporter; tflite::ErrorReporter* error_reporter = µ_error_reporter; const tflite::Model* model = nullptr; tflite::MicroInterpreter* interpreter = nullptr; TfLiteTensor* input = nullptr; TfLiteTensor* output = nullptr; // Create an area of memory to use for input, output, and intermediate arrays. constexpr int kTensorArenaSize = 10 * 1024; uint8_t tensor_arena[kTensorArenaSize]; const uint8_t image_data[128*128] = { 0, 0, 0, ..., 255, // Example values // ... (rest of the data) } } // namespace void setup() { Serial.begin(115200); // Load the model model = tflite::GetModel(model_mobilenetv2_tflite); if (model->version() != TFLITE_SCHEMA_VERSION) { Serial.println("Model schema version does not match"); while (1); } // Create an interpreter to run the model static tflite::MicroMutableOpResolver<10> micro_op_resolver; tflite::MicroInterpreter static_interpreter( model, micro_op_resolver, tensor_arena, kTensorArenaSize, error_reporter); interpreter = &static_interpreter; // Allocate memory from the tensor_arena for the model's tensors interpreter->AllocateTensors(); // Obtain pointers to the model's input and output tensors input = interpreter->input(0); output = interpreter->output(0); for (int i = 0; i < input->bytes; i++) { input->data.uint8[i] = image_data[i]; } } void loop() { // Run the model on this input and make sure it succeeds if (interpreter->Invoke() != kTfLiteOk) { Serial.println("Invoke failed"); while (1); } // Output the results for (int i = 0; i < output->dims->data[1]; i++) { Serial.print("Output["); Serial.print(i); Serial.print("]: "); Serial.println(output->data.uint8[i]); } delay(1000); }
问题根源与解决方法
1. 模型存储位置错误(核心问题)
.dram0.data占用10MB的主要原因是MobileNetV2模型被编译到RAM的.data段,而模型本身大小远超320KB的RAM容量。
解决:将模型移到Flash存储
ESP32的SPI Flash容量远大于RAM,需把模型放到Flash只读区域:
- 在Arduino环境中,用
PROGMEM宏修饰模型变量:// 修改model.h中的模型定义,或在引用时添加PROGMEM extern const uint8_t model_mobilenetv2_tflite[] PROGMEM; extern const size_t model_mobilenetv2_tflite_len; - 加载模型时直接从Flash读取,无需复制到RAM:
model = tflite::GetModel(model_mobilenetv2_tflite);
2. 示例图像数据的内存优化
代码中image_data[128*128]是16KB的全局数组,可进一步优化:
- 若仅用于测试,直接在
setup()中动态生成测试数据,移除全局数组:for (int i = 0; i < input->bytes; i++) { input->data.uint8[i] = random(0, 255); // 生成随机测试数据 } - 若需固定图像,同样用
PROGMEM放到Flash,读取时用pgm_read_byte():const uint8_t image_data[128*128] PROGMEM = {0, 0, 0, ...}; // 读取数据 input->data.uint8[i] = pgm_read_byte(&image_data[i]);
3. Tensor Arena大小调整
当前kTensorArenaSize = 10KB远小于MobileNetV2的需求,会导致张量分配失败:
- 先增大到128KB测试,后续再根据实际情况优化:
constexpr int kTensorArenaSize = 128 * 1024; uint8_t tensor_arena[kTensorArenaSize];
4. 模型轻量化
MobileNetV2对320KB RAM设备仍有压力,建议进一步压缩:
- 使用TensorFlow Lite模型优化工具进行int8量化,可将模型大小和内存占用降低75%左右。
- 替换为更轻量的模型,比如MobileNetV1、SqueezeNet,或TensorFlow Lite Micro官方提供的PersonDetection等微控制器专用模型。
内容的提问来源于stack exchange,提问作者sats
相关产品推荐
相关产品推荐

