GPytorch:用faiss-cpu初始化VNNGP模型后切换CUDA报错求助
核心错误原因
你遇到的RuntimeError: indices should be either on cpu or on the same device as the indexed tensor (cpu),本质是用于索引的张量和被索引的张量设备不匹配——报错信息明确被索引张量在CPU,而你的索引张量(或被索引张量)跨设备了。
结合你的场景,矛盾点在于:faiss-cpu只能在CPU上运行,NNVariationalStrategy中基于faiss的nn_util生成的邻居索引(即current_training_indices)默认留在CPU,但你把模型和训练数据移到了CUDA,直接触发了设备不匹配。
针对性解决方法
方法1:统一所有张量到CPU
既然faiss-cpu只能在CPU工作,直接把模型和训练数据都放在CPU环境训练:
# 取消train_x = train_x.cuda()操作 model = model.cpu() # 后续训练流程保持在CPU环境执行
这种方式能彻底避免设备不匹配问题,缺点是训练速度会受影响,但能保证流程正常跑通。
方法2:手动同步索引张量设备
如果坚持用CUDA训练模型,需要在训练过程中手动把动态生成的current_training_indices移到CUDA。由于该张量是训练时实时生成的,需在每个训练步骤/epoch前同步设备:
# 先把模型和训练数据移到CUDA model = model.cuda() train_x = train_x.cuda() # 在训练循环内,每次执行训练前同步索引设备 model.variational_strategy.current_training_indices = model.variational_strategy.current_training_indices.cuda() # 再执行训练步骤
注意:如果current_training_indices是每个batch重新生成的,需要在每个batch前重复执行上述同步操作。
方法3:定位具体出错的张量
若想明确到底是哪两个张量不匹配,可以通过打印完整错误栈定位:
import traceback try: # 你的完整训练代码 model.train() for epoch in range(num_epochs): # 训练步骤逻辑 ... except RuntimeError as e: traceback.print_exc()
错误栈会显示报错发生的具体代码行,你可以在该行打印相关张量的设备(比如indices.device和被索引张量的device),就能精准定位问题所在。
关于你之前操作的补充说明
你单独设置inducing_points和nn_util到CUDA的操作无法解决根本问题:因为nn_util基于faiss-cpu,它的索引计算始终在CPU完成,生成的current_training_indices还是会留在CPU。必须手动同步这个张量的设备,或者统一全量到CPU。
内容的提问来源于stack exchange,提问作者krugan

