Pytorch-训练学习

Pytorch-训练学习

Autograd

autograd类为计算导数的引擎(雅可比向量积),雅可比矩阵的概念参考这篇博文,autograd记录了梯度张量上所有操作的一个图,并创建了一个称为动态计算图的非循环图。这个图的叶节点是输入张量,根节点是输出张量。梯度是通过跟踪从根到叶的图形,并使用链式法则将每个梯度相乘来计算的。
1.跟踪tensor上的所有操作,设置属性requires_grad=True

x = torch.randn(3,3,requires_grad=True)

2.自动计算所有梯度,调用.backward()

y = (x*2).sum()
y.backward()
print(y.requires_grad) # True

3.停止跟踪tensor,调用.detach()或使用代码块with torch.no_grad()

with torch.no_grad():
	print((x*2).requires_grad) # False
y = y.detach()
print(y.requires_grad) # False

4.若tensor不仅仅是标量,需要靠gradient参数来说明张量的形式

y_ = x*2
v = torch.randn(3,3)
y_.backward(v)
print(x.grad) # x的导数

5..grad_fn属性是对tensor计算一次就引用一次Function对象,来产生运算结果,记录运算的发生,保存记录运算的输入,tensor使用.grad.fn属性记录这个计算图的入口,反向传播中,autograd引擎会按照逆序,通过function的backward依次计算梯度,grad_fn相当于指针,指向的是Function对象的地址。

DP模式训练(DataParallel)

pytorch中的GPU操作默认是异步的,当调用一个使用GPU的函数时,这些操作会在特定设备上排队但不一定在稍后执行。这使用pytorch具有并行计算的能力。
在平时训练中使用最多的就是多GPU并行计算,pytorch中的多GPU并行计算是数据级并行,相当于开了多个进程,每个进程自己独立运行,最后再整合在一起。

from torch.nn import DataParallel as DP
device_ids = [0,1,2]
net = DP(net,device_ids=device_ids)

上面提到的DataParallel函数,通过源码来看一下它的作用

DataParallel(module,device_ids=None,output_device=None,dim=0)
module:每个模型都要拷贝一份数据
device_ids:存储gpu的列表
output_device:输出gpu,默认为第一块卡(index=0),虽然输入计算由几块卡均分,但是输出loss的计算由这一张卡独自承担,这造成了这张卡所承受的计算量要大于其他参与训练的卡

下面来说下DP是如何进行并行计算的
在前向传播中,输入batch会被划分成多个子batch并送到不同的gpu(device)中进行计算,而你的module是在每个gpu上进行复制,简而该之,输入的batch会被平均分配到每个gpu中,但是module要拷贝到每个gpu中,每个gpu中的module只需要处理它被分配到的子batch即可(注意:你的batch要大于gpu个数)。再在反向传播过程中,每个子batch的梯度被累加到原始模块中(汇总的过程)。
注意:在运行DP模块之前,并行化模块必须在device_ids[0]上具有其参数和缓冲区。在执行DP前,会先把模型的参数放在device_ids[0]上。但是实际开发中,假如八卡服务器的0号显卡被人占用,那么你只能用2,3号卡来训练,但是你不能直接指定device_ids=[2,3],这样会出现模型初始化的bug,也就是你的module没有复制到device_ids[0]上。所以你必须在训练前添加如下两句话

os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "2,3"

此时device_ids[0]默认的就是2号卡了

扫描二维码关注公众号,回复: 13222825 查看本文章

参考Pytorch 的 nn.DataParallel 详细解析

猜你喜欢

转载自blog.csdn.net/qq_35140742/article/details/121135178