PyTorch下,使用list放置模块,导致计算设备不一的报错

报错

在复现 Transformer 代码的训练阶段时,发生报错:

bash 复制代码
RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu!

解决方案

通过next(linear.parameters()).device确定 model 已经在 cuda:0 上了,同时输入 model.forward()的张量也位于 cuda:0。输入的张量没什么好推敲的,于是考虑到模型具有多层结构,遂输出每层结构的设备信息,model.encoder -> model.encoder.sublayer[0] ··· ···

测试发现,model.encoder.sublayer[0] 之后的模块的设备信息均位于 cpu,原因是构造这部分模块时,由于需要多个相同的模块,使用了 list 来存放模块:

python 复制代码
# module: 需要深拷贝的模块
# n: 拷贝的次数
# return: 深拷贝后的模块列表
def clones(module, n: int) -> list:
    return [copy.deepcopy(module) for _ in range(n)]

显然 list 不支持 GPU,需要用 PyTorch 提供的代替:

python 复制代码
def clones(module, n: int):
    return nn.ModuleList([copy.deepcopy(module) for _ in range(n)])

ModuleList 把子模块存入列表,能像 Python 里普通的列表被索引,最重要的是能使内部的模块被正确注册,并对所有的 Module 方法可见。[Source]

成功解决!

相关环境

bash 复制代码
python                    3.11.7               he1021f5_0
pytorch                   2.1.2           py3.11_cuda12.1_cudnn8_0    
相关推荐
2301_8038756112 小时前
Redis如何通过永不过期策略规避击穿
jvm·数据库·python
2301_8166602112 小时前
CSS中relative与absolute的区别_详解相对与绝对定位应用场景
jvm·数据库·python
qq_4609784012 小时前
Golang怎么JWT设置过期时间_Golang如何在Claims中配置Token有效期【操作】
jvm·数据库·python
weixin_5689960613 小时前
Cgo 中正确设置 C 结构体回调函数指针的完整方案
jvm·数据库·python
Jun62613 小时前
【RV1103】AD4115实现8通道ADC采样,MQTT数据传输,1K采样率
linux·python
LiAo_1996_Y13 小时前
mysql如何限制特定存储过程执行权限_MySQL存储过程安全访问
jvm·数据库·python
knight_9___13 小时前
LLM工具调用面试篇1
开发语言·人工智能·python·面试·agent
2601_9561394213 小时前
快消品品牌全案公司哪家强
大数据·人工智能·python
源码之家13 小时前
Python股票数据分析与预测系统 大数据项目
大数据·python·机器学习·数据挖掘·数据分析·股票·可视化
甄心爱学习13 小时前
【项目实训(个人5)】
python·github