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

HuggingFace模型封装调用多encoder时出现cpu/cuda张量设备不匹配错误

问题根因

你的报错核心原因是普通Python列表存储的PyTorch子模块不会被父模型自动识别和迁移设备:

  • 单encoder场景下你大概率是直接将encoder作为父模型的类属性(比如self.encoder = XXXEncoder()),调用model.to('cuda')时PyTorch会自动识别子模块,完成参数迁移
  • 多encoder场景下你把所有encoder存到了普通Python列表self.prompt_encoders中,PyTorch的nn.Module机制不会遍历普通列表中的子元素做设备迁移,因此其余encoder的参数都留在了CPU上,forward调用时就会触发CPU/CUDA设备不匹配的报错
  • 你现有代码中调用encoder(xxx).to(device)是在推理完成后才迁移结果,推理过程中encoder参数和输入张量的设备已经不匹配,因此这行代码的转移动作无法解决报错
可行解决方案

最优方案:将存储容器替换为nn.ModuleList

这是PyTorch官方推荐的多子模块存储方案,修改后父模型调用to()方法时会自动遍历nn.ModuleList中的所有子模块完成设备迁移,操作步骤如下:

  1. 找到你父模型中初始化self.prompt_encoders的代码,将普通列表替换为nn.ModuleList:
import torch.nn as nn
# 原来的写法(错误)
# self.prompt_encoders = []
# 替换为
self.prompt_encoders = nn.ModuleList()

# 后续添加encoder的逻辑保持不变,还是用append
self.prompt_encoders.append(your_encoder_instance)
  1. 正常调用父模型的设备迁移方法即可,所有子encoder会自动同步设备:
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model = YourHuggingFaceWrapperModel().to(device)

临时验证方案(不推荐用于训练,性能损失大)

如果不想修改初始化逻辑,可在forward循环中临时迁移encoder参数到输入所在设备,修改你的报错代码段即可:

for encoder in self.prompt_encoders:
    wlog.info("********** offset: %s, length: %s", encoder.id_offset, encoder.length)
    prompt_token_fn = encoder.get_prompt_token_fn()
    encoder_masks = prompt_token_fn(input_ids)
    wlog.info("Encoder masks: %s", encoder_masks)
    if encoder_masks.any():
        prompt_input_ids = input_ids[encoder_masks]
        wlog.info("Prompt Input ids: %s", prompt_input_ids)
        # 新增:将encoder临时迁移到输入张量所在设备
        encoder = encoder.to(input_ids.device)
        prompt_embeds = encoder(prompt_input_ids, prompt_ids).to(device=inputs_embeds.device)

内容的提问来源于stack exchange,提问作者Ahmad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 12:15:02