Pytorch:关于nn.dataParallel我所踩过的坑
- 报错一:module must have its parameters and buffers on device cuda:1 (device_ids[0]) but found one of them on device: cpu
- 报错二:RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cuda:1! (when checking arugment for argument index in method wrapper_index_select)
- 问题一:速度变慢
报错一:module must have its parameters and buffers on device cuda:1 (device_ids[0]) but found one of them on device: cpu
假设有4张卡,他的运行机制是
- 首先把所有权重与tensor都先加载到第一张卡
- 然后通过第一张卡在分发给其余的卡
出现这个原因是我刚开始定义模型的时候直接调用了:
m = torch.nn.DataParallel(m, device_ids=[1,0,2,3])
这行代码应该代表了第二步,应该改正为:
m = m.to('cuda:1')
m = torch.nn.DataParallel(m, device_ids=[1,0,2,3])
报错二:RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cuda:1! (when checking arugment for argument index in method wrapper_index_select)
这个报错的大概意思说你的模型内部又新定义了一个tensor,并且它没有与计算图关联,dataParallel不会把这个tensor分发给其他的卡,但是我一开也意识到了这点,所以给这个tensor定义了 device=‘cuda:1’,于是就有了上面的error,如果没有这个操作,那么就与报错一相同。
修改方法:
把新创建的device的设置为 可以被dataParallel分发的device(如demo),比如:
new_tensor = torch.arange(10, device=demo.device)
问题一:速度变慢
很多同学发现在进行多GPU运算时,程序花费的时间反而更多了,这其实是因为你的batch_size太小了,因为torch.nn.DataParallel()这个函数是将每个batch的数据平均拆开分配到多个GPU上进行计算,计算完再返回来合并。这导致GPU之间的开关和通讯过程占了大部分的时间开销。
可以使用watch -n 1 nvidia-smi这个命令来查看每1s各个GPU的运行情况,如果发现每个GPU的占用率均低于50%,基本可以肯定你使用多GPU计算所花的时间要比单GPU计算花的时间更长了。