RuntimeError: Expected query, key, and value to have the same dtype, but got query.dtype: float key.dtype: c10::Half and value.dtype: c10::Half instead.

该报错通常出现在 Apple M 系列芯片(MPS 设备)上使用 Accelerate 开启混合精度(如 fp16)训练时:Accelerate 的 autocast 仍走 torch.cuda.amp.autocast ,而当时 PyTorch 尚不支持 MPS autocast,导致上下文内外的

快速结论:该报错通常出现在 Apple M 系列芯片(MPS 设备)上使用 Accelerate 开启混合精度(如 fp16)训练时:Accelerate 的 autocast 仍走 torch.cuda.amp.autocast,而当时 PyTorch 尚不支持 MPS autocast,导致上下文内外的张量精度不一致。优先排查所用 PyTorch 是否已支持 MPS autocast,以及 attention 中 query/key/value 的 dtype 是否统一。

适用环境:Issue 中确认的环境为 accelerate==0.18.0、M2 Mac、macOS 13.3.1;相关讨论还涉及在 conda(Python 3.10)环境中从源码编译带 MPS autocast 补丁的 PyTorch,以及 diffusers 的 DreamBooth LoRA SDXL 脚本。其余版本信息未在 Issue 中确认。

最快修复方案:暂无确认的一步修复方案。Issue 中的结论是需等待 PyTorch 先在 MPS 上支持 autocast,Accelerate 才能跟进适配;单纯修改 Accelerate 的 autocast 逻辑并不能完整解决问题。

注意事项:手动给 PyTorch 打补丁并从源码编译属于实验性做法,Issue 中该做法后续仍触发了 dtype 不一致报错,并未验证成功;在 MPS 上使用 fp16 混合精度训练在相关版本中仍属未完成支持,不建议直接用于生产。

问题场景

用户在 Apple M2(macOS 13.3.1)上使用 accelerate==0.18.0 运行自己的训练脚本,希望通过 Accelerator(mixed_precision="fp16") 配合 accelerator.autocast() 在 MPS 设备上启用自动混合精度。随后有用户在 diffusers 的 DreamBooth LoRA SDXL 训练脚本中尝试该能力:先为本地 PyTorch 手动复制 MPS autocast 相关补丁并从源码编译,再在 UNet 的 attention 计算中触发了下述 dtype 不一致报错。

报错原文

RuntimeError: Expected query, key, and value to have the same dtype, but got query.dtype: float key.dtype: c10::Half and value.dtype: c10::Half instead.

其后还伴随进程终止信息:

libc++abi: terminating due to uncaught exception of type std::__1::system_error: recursive_mutex lock failed: Invalid argument

原因分析

最可能的原因:在 accelerate 0.18.0 的 autocast 实现中,mixed_precision == "fp16" 分支固定调用 torch.cuda.amp.autocast(dtype=torch.float16),并未针对 MPS 设备分支处理。当时 PyTorch 的 MPS 后端尚未支持 autocast(对应 pytorch/pytorch#88415),因此 Accelerate 侧无法直接适配,官方回复也是等待 PyTorch 先落地该特性。

在用户手动打补丁的场景中,autocast 已能让部分张量进入半精度,但 attention 里传入 scaled_dot_product_attention 的 query 仍为 float(c10::float),而 key/value 已变为 c10::Half,三者在算子内 dtype 不匹配,从而抛出该 RuntimeError。这可能是 MPS autocast 补丁覆盖不完整、或 attention 输入未统一参与 autocast 所致。

环境排查

  • 确认设备为 Apple Silicon(MPS),操作系统版本(Issue 为 macOS 13.3.1)。
  • 确认 accelerate 版本(Issue 为 0.18.0),检查其 autocast 代码是否仍硬编码 torch.cuda.amp.autocast。
  • 确认所用 PyTorch 是官方发行版还是自行打补丁、从源码编译的版本,以及该版本是否声明支持 MPS autocast。
  • 确认 Python 与 conda 环境(Issue 中为 Python 3.10 的 conda 环境)。
  • 确认训练脚本中的 mixed_precision 设置,以及模型输入、attention 中 query/key/value 的实际 dtype。
  • 如使用 diffusers 示例脚本,一并记录其版本与 UNet/attention 相关配置。

解决步骤

  1. 先不要指望仅修改 Accelerate 就能修复。确认当前 PyTorch 是否已支持 MPS autocast(参考 pytorch/pytorch#88415 的状态),未支持时在 MPS 上开启 fp16 混合精度本身就不具备完整支持。
  2. 若只是要恢复训练,可优先尝试关闭混合精度(不启用 mixed_precision="fp16" 或不在 autocast 上下文中运行),确认问题是否只与 autocast 相关。
  3. 若坚持在 MPS 上尝试混合精度,需要自行在 PyTorch 侧准备支持 MPS autocast 的构建(Issue 中用户参考 pytorch/pytorch#99272 打补丁并源码编译),这属于实验性做法。
  4. 在出现 dtype 报错的位置(attention 计算前)检查 query/key/value 的 dtype,定位哪一侧未跟随 autocast 转为半精度,判断是补丁覆盖不全还是输入转换缺失。
  5. 关注 PyTorch 与 Accelerate 后续版本是否正式加入 MPS autocast 支持,届时再按官方文档启用 mixed_precision。

验证方法

重新运行触发报错的训练步骤,确认不再出现 RuntimeError: Expected query, key, and value to have the same dtype...,且训练能正常迭代、损失正常下降。若只是暂时关闭混合精度,可通过能顺利跑完若干 step 来确认问题来自 autocast 而非模型或数据本身。

参考来源

huggingface/accelerate #1396

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 34975

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注