【参考资料】
http://pytorch.org/docs/master/nn.html#dataparallel-layers-multi-gpu-distributed
《深度学习框架PyTorch入门与实践》
【机器配置】型号:华硕ESC8000G3。内存128G,八块Nvidia GTX TITAN X。
【测试例子】AI Challenge挑战赛-场景分类()
一、GPU并行方式
通过对模型进行并行GPU处理(这里一般指单机多卡),可以相对提高处理速度,但是处理方法大致有两种。
将Module放在GPU上运行也十分简单,只需两步:
model = model.cuda():将模型的所有参数转存到GPU
input.cuda():将输入数据也放置到GPU上
至于如何在多个GPU上并行计算,PyTorch也提供了两个函数,可实现简单高效的并行GPU计算。
①nn.parallel.data_parallel(module, inputs, device_ids=None, output_device=None, dim=0, module_kwargs=None)
②class torch.nn.DataParallel(module, device_ids=None, output_device=None, dim=0)
可见二者的参数十分相似,通过device_ids参数可以指定在哪些GPU上进行优化,output_device指定输出到哪个GPU上。唯一的不同就在于前者直接利用多GPU并行计算得出结果,而后者则返回一个新的module,能够自动在多GPU上进行并行加速。
# method 1
new_net = nn.DataParallel(net, device_ids=[0, 1])
output = new_net(input)
# method 2
output = nn.parallel.data_parallel(new_net, input, device_ids=[0, 1])
DataParallel并行的方式,是将输入一个batch的数据均分成多份,分别送到对应的GPU进行计算,各个GPU得到的梯度累加。与Module相关的所有数据也都会以浅复制的方式复制多份,在此需要注意,在module中属性应该是只读的。
model = Model(input_size, output_size)
if torch.cuda.device_count() > 1:
print("Let's use", torch.cuda.device_count(), "GPUs!")
# dim = 0 [30, xxx] -> [10, ...], [10, ...], [10, ...] on 3 GPUs
model = nn.DataParallel(model)
if torch.cuda.is_available():
model.cuda()
二、运行过程中遇到的问题
近期对这两种方法进行了尝试,对于PIL Image来说,需要处理成Tensor,然后进行归一化。这两种方法如果不对device_ids参数进行设置,默认会使用所有的GPU。并行期间GPU使用率大部分在40%——50%之间。
【问题】在用DataParallel方法后,在并行处理过程中会报如下错误:RuntimeError: all tensors must be on devices[0]。
但是使用nn.parallel.data_parallel方法后不会存在这个问题。估计可能是返回的新的moudle问题。
if torch.cuda.device_count() > 1:
# model = nn.DataParallel(model)
# outputs = model(inputs)
outputs = nn.parallel.data_parallel(model, inputs)
else:
outputs = model(inputs)
在测试过程中也会发现,当指定GPU为4块的时候每跑一轮的时间都会比全部使用的时间短。
除了以上的报错之外,在使用中会出现一个警告:UserWarning: PyTorch is not compiled with NCCL support。PyTorch不支持NCCL编译是个什么意思?。。。