You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 = &micro_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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 21:55:11