Skip to content

[Express:Bugfix] Fix loadMap/load output readMap returning NULL - #4751

Merged
wangzhaode merged 1 commit into
alibaba:masterfrom
fshuang8299:fix/loadmap-output-readmap
Aug 12, 2026
Merged

[Express:Bugfix] Fix loadMap/load output readMap returning NULL#4751
wangzhaode merged 1 commit into
alibaba:masterfrom
fshuang8299:fix/loadmap-output-readmap

Conversation

@fshuang8299

Copy link
Copy Markdown
Contributor

Description

Variable::load / Variable::loadMap 加载的模型,输入可写(#4733 修复后)、推理可算,
但输出 readMap 返回 NULL——expressDemo 修复 #4733 后不崩但仍无输出。

Root causeVariable::load 对非 INPUT 节点执行 Tensor::clone(allTensors[i])
clone 共享源 describe(memoryType 默认 MEMORY_BACKEND),覆盖了 Expr::create
正确设置的 MEMORY_HOST。mapOutput 拷贝分支(allocMemoryForHostTensor 要求
MEMORY_HOST)无法分配 host → readMap 返回 NULL。

Fix:clone 后恢复 memoryType = MEMORY_HOST(与 #4733 的 INPUT 分支同源修复)。

// express/Expr.cpp(Variable::load 的 clone 分支内)
expr->inside()->mOutputTensors[index] = Tensor::clone(allTensors[outputIndex].get());
// 还原 Expr::create 的正确状态(memoryType=MEMORY_HOST)
TensorUtils::getDescribe(expr->inside()->mOutputTensors[index])->memoryType = Tensor::InsideDescribe::MEMORY_HOST;

Module

Express

Type

  • Feature
  • Bugfix
  • Perf
  • Refact
  • Style
  • Doc
  • Test
  • Chore

Checklist

  • Commit message follows [Module:Type] Description format
  • Code compiles without errors
  • Tested on relevant platform(s)
  • No unrelated format or style changes included

Reproduction

模型由代码生成,无需附件(完整可编译示例见 issue #4750)。核心流程:

Variable::save({y}, "tiny.mnn");              // 生成 Conv3x3+ReLU 模型(输入 1x3x8x8 NCHW)
auto varMap = Variable::loadMap("tiny.mnn");
auto io = Variable::getInputAndOutput(varMap);
auto input = io.first.begin()->second, output = io.second.begin()->second;
auto ptr = input->writeMap<float>();          // ✅ OK(#4733 后)
// 写输入 0.5...
auto out = output->readMap<float>();          // ❌ 修复前 NULL → 修复后有效值

Verification

  • ✅ 修复前后对比(临时还原 B1 实测):readMap NULL → 1.36(数学正确:27×0.1×0.5+0.01)
  • ✅ 新增回归测试 expr/LoadMapOutputReadMap 通过(独立验证)
  • ✅ expr/ 全量单测 54 个通过(53 原有 + 新增 1)
  • ✅ Module API / Session API 正常(1.36,无副作用)
  • ✅ Const / 重复 readMap / resize 专项通过
  • ✅ 量化模型 readMap 非 NULL(量化输出数值精度为量化链路本身问题,与本 PR 无关)
  • 注:MNN 全量测试套件在 x86 批跑有卡点(op/InterpInt8、op/randomuniform 单独跑通过但批跑卡)——已用原始 master 对照实验确认与本次修改无关

Scope

本 PR 严格限定 Express Variable::load 的输出路径(1 行修复 + 回归测试)。
不影响:Module API / Session API / Const 节点 / 输入路径(#4733 已处理)。

Related

@CLAassistant

CLAassistant commented Aug 10, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@wangzhaode wangzhaode added the type:bug 功能缺陷 label Aug 11, 2026
@wangzhaode wangzhaode self-assigned this Aug 11, 2026
@wangzhaode

Copy link
Copy Markdown
Collaborator

Thanks for the fix. Could you please make two cleanup changes before merging?

  1. Please rebase this branch onto the latest master and drop commit c47c693d from [Express:Bugfix] Fix loadMap input tensor losing host buffer #4733, since that change has already been merged. This PR should contain only the additional output readMap() fix for Express loadMap/load 输出读取失败:output VARP 的 readMap 返回 NULL #4750.
  2. These two small loadMap regression cases do not need separate test source files. After rebasing, test/expr/LoadMapInputTest.cpp already exists on master; please add the output readMap() regression case to that existing file (or consolidate both cases into one common LoadMap test file) and remove test/expr/LoadMapOutputTest.cpp.

The functional fix itself looks reasonable. Thanks!

Variable::load replaces non-INPUT tensors with Tensor::clone(allTensors[i]),
which shares the source describe carrying memoryType=MEMORY_BACKEND (default),
overwriting the MEMORY_HOST that Expr::create correctly set. As a result
mapOutput's copy branch fails to allocate a host buffer and readMap() on the
model output returns NULL.

Fix: restore memoryType=MEMORY_HOST after the clone in Variable::load.
Safe: the cloned tensor's host is null for non-CONST nodes (CONST/TRAIN nodes
don't enter this branch), so restoring MEMORY_HOST cannot cause a double-free
on destruction.

Add regression test expr/LoadMapOutputReadMap.

Fixes alibaba#4750
@fshuang8299
fshuang8299 force-pushed the fix/loadmap-output-readmap branch from 370542d to 316dade Compare August 11, 2026 03:41
@fshuang8299

Copy link
Copy Markdown
Contributor Author

Thanks for the review! Both cleanup changes are done:

  1. Rebased onto the latest master and dropped c47c693 (from [Express:Bugfix] Fix loadMap input tensor losing host buffer #4733, already merged). This PR now contains only the output readMap() fix for Express loadMap/load 输出读取失败:output VARP 的 readMap 返回 NULL #4750.

  2. Consolidated tests: added the expr/LoadMapOutputReadMap regression case into the existing test/expr/LoadMapInputTest.cpp and removed LoadMapOutputTest.cpp.

Verified after rebase: expr/ suite passes (54 cases, including both expr/LoadMapInputWriteMap and expr/LoadMapOutputReadMap).

@wangzhaode
wangzhaode merged commit 8abc413 into alibaba:master Aug 12, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:bug 功能缺陷

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Express loadMap/load 输出读取失败:output VARP 的 readMap 返回 NULL

3 participants