Parallel processing RuntimeError:模块必须在设备cuda:1(设备_ID[0])上具有其参数和缓冲区,但在设备cuda:2上找到了其中一个参数和缓冲区

Parallel processing RuntimeError:模块必须在设备cuda:1(设备_ID[0])上具有其参数和缓冲区,但在设备cuda:2上找到了其中一个参数和缓冲区,parallel-processing,pytorch,Parallel Processing,Pytorch,我有4个GPU(0,1,2,3),我想在GPU 2上运行一个Jupyter笔记本,在GPU 0上运行另一个。所以执行之后, export CUDA_VISIBLE_DEVICES=0,1,2,3 对于GPU 2笔记本,我有 device = torch.device( f'cuda:{2}' if torch.cuda.is_available() else 'cpu') device, torch.cuda.device_count(), torch.cuda.is_available()

我有4个GPU(0,1,2,3),我想在GPU 2上运行一个Jupyter笔记本,在GPU 0上运行另一个。所以执行之后,

 export CUDA_VISIBLE_DEVICES=0,1,2,3
对于GPU 2笔记本,我有

device = torch.device( f'cuda:{2}' if torch.cuda.is_available() else 'cpu')
device, torch.cuda.device_count(), torch.cuda.is_available(), torch.cuda.current_device(), torch.cuda.get_device_properties(1)
创建新模型或加载模型后

model = nn.DataParallel( model, device_ids = [ 0, 1, 2, 3])
model = model.to( device)
然后,当我开始训练模特时

RuntimeError                              Traceback (most recent call last)
<ipython-input-18-849ffcb53e16> in <module>
 46             with torch.set_grad_enabled( phase == 'train'):
 47                 # [N, Nclass, H, W]
 ---> 48                 prediction = model(X)
 49                 # print( prediction.shape, y.shape)
 50                 loss_matrix = criterion( prediction, y)

~/.local/lib/python3.6/site-packages/torch/nn/modules/module.py in __call__(self, *input, **kwargs)
491             result = self._slow_forward(*input, **kwargs)
492         else:
--> 493             result = self.forward(*input, **kwargs)
494         for hook in self._forward_hooks.values():
495             hook_result = hook(self, input, result)

~/.local/lib/python3.6/site-packages/torch/nn/parallel/data_parallel.py in forward(self, *inputs, **kwargs)
144                 raise RuntimeError("module must have its parameters and buffers "
145                                    "on device {} (device_ids[0]) but found one of "
--> 146                                    "them on device: {}".format(self.src_device_obj, t.device))
147 
148         inputs, kwargs = self.scatter(inputs, kwargs, self.device_ids)

RuntimeError: module must have its parameters and buffers on device cuda:0 (device_ids[0]) but found one of them on device: cuda:2
运行时错误回溯(最近一次调用)
在里面
46带火炬。设置梯度启用(相位=‘列车’):
47#[N,N类,H,W]
--->48预测=模型(X)
49#打印(预测形状,y形状)
50损失矩阵=标准(预测,y)
~/.local/lib/python3.6/site-packages/torch/nn/modules/modules.py in\uuuuu调用(self,*input,**kwargs)
491结果=self.\u slow\u forward(*输入,**kwargs)
492其他:
-->493结果=自我转发(*输入,**kwargs)
494用于钩住自身。\u向前\u钩住.values():
495钩子结果=钩子(自身、输入、结果)
~/.local/lib/python3.6/site-packages/torch/nn/parallel/data_parallel.py前进(self,*输入,**kwargs)
144 raise RUNTIMERROR(“模块必须有其参数和缓冲区”
145“在设备{}(设备_id[0])上,但找到以下之一”
-->146“设备上的它们:{}”。格式(self.src_device_obj,t.device))
147
148个输入,kwargs=self.scatter(输入,kwargs,self.device_id)
RuntimeError:模块必须在设备cuda:0(设备_ID[0])上具有其参数和缓冲区,但在设备cuda:2上找到了其中一个参数和缓冲区

DataParallel
要求在其
设备ID
列表中的第一个设备上提供每个输入张量

它基本上在分散到其他GPU之前将该设备用作暂存区,并且在从前进返回之前在该设备中收集最终输出。如果希望设备2成为主要设备,则只需将其放在列表的前面,如下所示

model = nn.DataParallel(model, device_ids = [2, 0, 1, 3])
model.to(f'cuda:{model.device_ids[0]}')
之后,提供给模型的所有张量也应该在第一个设备上

x = ... # input tensor
x = x.to(f'cuda:{model.device_ids[0]}')
y = model(x)

对我来说,甚至还有以下工作:

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
if torch.cuda.device_count() > 1:
    print("Let's use", torch.cuda.device_count(), "GPUs!")
    network = nn.DataParallel(network)

network.to(device)
tnsr = tnsr.to(device)

使用火炬时发生此错误,模型和数据均不在cuda上:

尝试使用类似的代码在cuda上建模和设置数据

model = model.toDevice(‘cuda’)
images = images.toDevice(‘cuda’)

DataParallel
要求在其
设备ID
列表中的第一个设备上提供每个输入张量。它基本上是在分散到其他GPU之前将该设备用作暂存区,并且在从forward返回之前在该设备中收集最终输出。我认为如果你想让设备2成为你的主要设备,那么
device\u id=[2,0,1,3]
就可以了,尽管我还没有测试过。我同意你的看法,因为设置device\u id=[2]是可行的。我希望DataParallel文档在这方面做得更好。今天晚些时候,我会回答这个问题。谢谢不会做
model.to(f'cuda:{model.device_ids[0]}')
只使用GPU 2而不满足模型并行的目的吗?我仍然得到
RuntimeError:模块必须在设备cuda:1上有它的参数和缓冲区(device_ids[0])但是在设备上找到了其中一个:cuda:0
该错误意味着model.to call I post实际上是必要的。调用model.to之后,您是否对模型参数或层进行了任何操作?请注意,model.to的目的是将模型中的缓冲区和参数移动到设备_id[0]因此,如果您遇到此错误,则会发生导致缓冲区或参数无法移动或在错误的设备上添加了新的参数或缓冲区的情况。@Coddy如果您无法解决此问题,请发布一个新问题,该问题会重现您看到的错误,我会查看。这是因为
device='cuda'
是与
device='cuda:0'
同义,后者是
DataParallel
的默认主设备。