【Bug已解决】`infer_auto_device_map` does not place submodule buffers on `device_map` when submodule is s
【Bug已解决】infer_auto_device_mapdoes not place submodule buffers ondevice_mapwhen submodule is split 解决方案一、现象长什么样用accelerate的infer_auto_device_map把一个大模型自动切到多张卡上。多数 submodule如每个decoder.layer.{i}会完整落在一张卡上但当一个 submodule 被拆分到两张卡之间时比如前几层在 GPU0、后几层在 GPU1这个被拆分的 submodule 里的buffer如LayerNorm的running_mean/running_var、loss_fn的缓存、位置编码表没有被写进device_map。于是 forward 时报RuntimeError Expected all tensors to be on the same device but found at least two devices cuda0 and cuda1或者更隐蔽地buffer 留在 CPUforward 时和 GPU 上的参数做运算 - device mismatch最小判据触发某个 submodule 跨设备被拆分split across GPUs 现象该 submodule 的 buffer 不在 device_map 中 后果buffer 滞留在原设备CPU/错误卡forward device mismatch 报错与否forward 时才暴露RuntimeError最迷惑的是大多数 submodule 正常只有被拆分到边界的那一个出问题。你盯着device_map看半天发现它的 parameters 都被分配了唯独 buffer 那几行缺席。二、背景infer_auto_device_map的产出是一个device_map字典module.path: cuda:0之类描述每个 module 落到哪张卡。accelerate在load_checkpoint_and_dispatch/dispatch_model时会按这个 map 用cpu_offload hook 把参数和 buffer 搬到对应设备。实现上算法是按 parameter 占用的显存逐步贪心分配从 GPU0 开始塞塞满就切到 GPU1。一个 submodule 若在边界被切断它的参数被分到两张卡。但 buffer 的处理与 parameter 是两套逻辑——buffer 的归属只在该 submodule完整落在某卡时才被记录一旦 submodule 被拆buffer 的归属分支被跳过于是 buffer 既没标 GPU0 也没标 GPU1。结果dispatch_model给 parameter 安了家却漏了 buffer。buffer 保持加载时的默认设备通常是 CPU或模型初始化的设备forward 时和已搬到 GPU 的参数做运算device mismatch 爆发。为什么完整 submodule没事因为完整时 buffer 分支正常执行只有拆分这个分支条件没覆盖 buffer才露出破绽。三、根因抽象成代码示意非照抄源码def infer_auto_device_map(model, ...): device_map {} for name, module in model.named_modules(): params_size sum(p.numel() for p in module.parameters()) if params_size 0: dev _assign_device(name, params_size) # 参数分配 device_map[name] dev # BUGbuffer 只在 module 完整落在一张卡时记录 # 若 module 被拆分参数跨卡buffer 分支被跳过 for bname, buf in module.named_buffers(): if not _module_was_split(name): device_map[f{name}.{bname}] dev # 拆分时漏了 return device_map根因链条infer_auto_device_map先给 parameters 分配设备可能把 submodule 拆到两张卡buffer 的归属逻辑依赖该 submodule 是否完整落在单卡的判断当 submodule 被拆分这个判断为 Falsebuffer 归属分支被跳过buffer 没进入device_mapdispatch_model只搬 device_map 里列出的张量buffer 滞留原设备forward 时参数在 GPU、buffer 在别处 - device mismatch。一句话buffer 的分配逻辑没有覆盖submodule 被拆分这一分支。四、最小可运行复现用纯 Python 模拟拆分 submodule 时 buffer 归属被漏掉# repro_buffer_split.py def infer_map(names, split_at): 模拟 device_map 推断参数分配 buffer 归属。 device_map {} split_names set(names[:split_at]) set(names[split_at:]) for n in names: device_map[n] cuda:0 if n split_at else cuda:1 # buffer 归属只在 module 未被拆分时记录 for n in names: if n in split_names: continue # BUG拆分的 module 漏掉 buffer device_map[n .buffer] device_map[n] return device_map def main(): # 假设 submodule block 的参数被拆到 cuda:0 和 cuda:1 names [block.p0, block.p1, block.p2] split_at 2 dm infer_map(range(3), split_at) has_buf any(k.endswith(buffer) and k.startswith(block) for k in dm) print(device_map 含 block 的 buffer, has_buf) assert not has_buf, 拆分 submodule 的 buffer 被遗漏 - 复现成功 if __name__ __main__: main()运行输出device_map 含 block 的 buffer False拆分后的block没有任何 buffer 进入device_map正是真实 bug 的抽象。五、解决方案第一层最小直接修复最小且必须的一步无论 submodule 是否被拆分都给它的 buffer 显式分配一个设备——通常放在持有该 submodule 最后一块参数的那张卡保证 forward 时 buffer 与大部分参数同设备# fix_layer1.py def fix_buffer_assignment(device_map, module_buffers, owner_of_last_param): for bname in module_buffers: # 拆分的 submodulebuffer 放到持有最后参数的卡保证同设备 device_map[bname] owner_of_last_param return device_map更稳妥地直接在infer_auto_device_map的补丁里把 buffer 归属从是否完整改成只要 module 有任何参数被分配就给它 buffer 也分配# 修复buffer 归属不再依赖 module 是否完整 for bname, buf in module.named_buffers(): owner device_map.get(name) or owner_of_last_param device_map[f{name}.{bname}] owner这一层改动最小补上拆分分支的 buffer 归属。但它用最后参数所在卡作为启发式若 submodule 参数均匀分散、buffer 该跟谁并非显然需第二层兜底。六、解决方案第二层结构性改进把buffer 归属做成确定性的规则buffer 跟随其所在 module 的主设备参数总字节数最多的那张卡并由单一函数统一计算不依赖是否拆分的判断# fix_layer2.py from dataclasses import dataclass from typing import Dict, List dataclass(frozenTrue) class TensorRef: name: str bytes: int device: str # 参数被分配到的设备 class DeviceMapBuilder: def __init__(self): self.params: List[TensorRef] [] self.buffers: List[TensorRef] [] def add_param(self, name, nbytes, device): self.params.append(TensorRef(name, nbytes, device)) def add_buffer(self, name, nbytes): self.buffers.append(TensorRef(name, nbytes, ?)) def primary_device_of(self, module_prefix: str) - str: 该 module 参数字节最多的设备作为 buffer 归属。 by_dev: Dict[str, int] {} for p in self.params: if p.name.startswith(module_prefix): by_dev[p.device] by_dev.get(p.device, 0) p.bytes return max(by_dev, keyby_dev.get) if by_dev else cpu def build(self) - Dict[str, str]: dm {p.name: p.device for p in self.params} for b in self.buffers: prefix b.name.rsplit(., 1)[0] dm[b.name] self.primary_device_of(prefix) # 跟随主设备 return dm要点primary_device_of用参数字节最多的设备决定 buffer 归属对拆分 submodule 也确定build对参数和 buffer 统一处理buffer 不再依赖是否完整分支任何拆分情况都落到明确设备forward 不会再 device mismatch。七、解决方案第三层断言 / CI 守护写 pytest 验证拆分 submodule 的 buffer 必在 device_map 中、且与参数同设备# test_device_map_buffers.py import pytest class FakeModel: def named_modules(self): return [(block, None)] def named_buffers(self, prefix): return [(block.running_mean, 1), (block.running_var, 1)] def infer_split_aware(names, split_at): dm {} for i, n in enumerate(names): dm[n] cuda:0 if i split_at else cuda:1 for n in names: dm[n .running_mean] dm[n] # 修复后总是记录 dm[n .running_var] dm[n] return dm def test_split_buffer_in_map(): names [block.p0, block.p1, block.p2] dm infer_split_aware(names, split_at2) assert block.p0.running_mean in dm assert block.p2.running_var in dm def test_buffer_same_device_as_its_param(): names [block.p0, block.p1, block.p2] dm infer_split_aware(names, split_at2) assert dm[block.p2.running_mean] dm[block.p2] def test_no_cpu_stranded_buffer(): names [block.p0] dm infer_split_aware(names, split_at1) for k in dm: if running in k: assert dm[k] ! cpu, buffer 不应滞留 CPUCI 一旦恢复成拆分时跳过 buffer前两个测试立刻变红。八、排查清单forward 报 device mismatch 且怀疑 buffer 时打印device_map搜索出问题的 submodule看其 buffer 是否在 map 中确认该 submodule 是否被拆分到多卡参数跨cuda:0/cuda:1若 buffer 行缺失命中本 bug按第五 / 六节给拆分 submodule 的 buffer 显式分配主设备用dispatch_model后检查 buffer 实际设备next(m.buffers()).device若用device_mapauto确认infer_auto_device_map版本是否已修复把第七节的 pytest 接进 CI守护拆分 submodule 的 buffer 必在 map。九、小结infer_auto_device_map在 submodule 被拆分到多卡时漏掉了该 submodule 的buffer归属——buffer 的分配逻辑只覆盖了module 完整落在单卡的分支拆分时被跳过。结果 buffer 滞留原设备forward 时与已搬走的参数 device mismatch。三层层级第一层拆分 submodule 的 buffer 显式分配到持有其最后参数 / 主设备的卡第二层用DeviceMapBuilder以参数字节最多的设备统一决定 buffer 归属消除拆分分支第三层pytest 验证拆分 submodule 的 buffer 必在 map 且与参数同设备锁进 CI。核心教训凡是按结构切分资源的算法必须保证被切分单元的每一种成员参数、buffer、状态都有归属任何只覆盖完整单元而漏掉被切分单元的分支都是隐性资源错位。

相关新闻

【计算机毕业设计】基于Vue框架+AI大模型身心健康日志系统

【计算机毕业设计】基于Vue框架+AI大模型身心健康日志系统

1.系统介绍随着社会压力增加,用户对身心健康管理的需求日益增长,传统身心健康管理方式存在交互性差、个性化不足等问题,难以满足用户多元化的情绪疏导、健康记录及社交需求。在此背景下,本研究设计并实现一套基于Vue框架AI大模型的…

2026/8/1 15:41:01 阅读更多 →
【Bug已解决】[Bug]: RNG states from multiple backends (e.g. CUDA + HPU) are saved but only one is restore

【Bug已解决】[Bug]: RNG states from multiple backends (e.g. CUDA + HPU) are saved but only one is restore

【Bug已解决】[Bug]: RNG states from multiple backends (e.g. CUDA HPU) are saved but only one is restored on load_state 解决方案 一、现象长什么样 在一个同时用到多种设备后端的环境里训练(例如模型主体在 CUDA 上、某些预处理 / 评估算子在 H…

2026/8/1 15:41:01 阅读更多 →
商业门头视觉升级,雕花铝单板塑造独特形象立面

商业门头视觉升级,雕花铝单板塑造独特形象立面

做过工装幕墙、写字楼大堂、商业综合体的设计师和采购都有同感:选材最怕的不是贵,而是“上墙就翻车”——色差、变形、曲面生硬、尺寸不对,返工一次次,工期一拖再拖。现在主流工装项目已经统一答案:全品类铝单板。但选…

2026/8/1 15:41:01 阅读更多 →

最新新闻

Unity SDK集成避坑指南:从Adjust实战到通用解决方案

Unity SDK集成避坑指南:从Adjust实战到通用解决方案

1. 项目概述:为什么Unity SDK集成总让人头疼?做Unity开发,尤其是涉及到广告变现、数据分析或者第三方服务接入时,集成SDK几乎是绕不开的一步。但说实话,这个过程很少一帆风顺。我见过太多开发者,从新手到老…

2026/8/2 18:58:00 阅读更多 →
Unity项目云端备份与协作:规避Google Drive同步冲突的三大实战方案

Unity项目云端备份与协作:规避Google Drive同步冲突的三大实战方案

1. 项目概述:Unity与Google Drive的“联姻”与常见痛点 如果你是一个Unity开发者,尤其是独立开发者或小团队的一员,那么“如何高效、安全地管理项目资产”这个问题,大概率让你头疼过。本地硬盘备份?容易丢失且版本混乱…

2026/8/2 18:58:00 阅读更多 →
Unity命令行构建实战:从环境配置到CI/CD集成的完整解决方案

Unity命令行构建实战:从环境配置到CI/CD集成的完整解决方案

1. 项目概述:为什么Unity控制台项目总让人头疼? 如果你是一名Unity开发者,尤其是从Unity编辑器转向命令行构建、自动化测试或者持续集成(CI/CD)流程,那么“控制台项目”这个概念你一定不陌生。它指的是不依…

2026/8/2 18:58:00 阅读更多 →
【Bug已解决】Feature Request: Add API to Materialize Meta Tensors for Device Movement 解决方案

【Bug已解决】Feature Request: Add API to Materialize Meta Tensors for Device Movement 解决方案

【Bug已解决】Feature Request: Add API to Materialize Meta Tensors for Device Movement 解决方案 一、现象长什么样 用 torch.device("meta") 建好大模型结构(省内存),之后想把它实体化(materialize)到真…

2026/8/2 18:58:00 阅读更多 →
Unity三维热力图实战:从网格生成到动态渲染全流程解析

Unity三维热力图实战:从网格生成到动态渲染全流程解析

1. 项目概述:三维热力图在Unity中的价值与挑战最近在做一个数据可视化的项目,客户的需求是把一堆抽象的数值,比如某个区域内的人口密度、温度分布或者信号强度,变成一个能让人一眼就看懂的三维立体模型。这让我立刻想到了三维热力…

2026/8/2 18:58:00 阅读更多 →
Unity可视化对话系统开发指南:基于xNode节点图构建

Unity可视化对话系统开发指南:基于xNode节点图构建

1. 项目概述:为什么选择 xNode 来构建对话系统?如果你在 Unity 里做过稍微复杂一点的游戏逻辑,比如 RPG 的任务对话、AVG 的文字冒险,或者任何需要分支选择的系统,大概率会对着一堆if-else、switch-case或者状态机感到…

2026/8/2 18:56:59 阅读更多 →

日新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/2 0:00:38 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/2 0:00:38 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/2 0:00:38 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/2 0:00:38 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/2 0:00:38 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/2 0:00:38 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/2 6:34:16 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/2 2:47:48 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/2 0:23:22 阅读更多 →