pytorch中 all_gather 操作是不进行梯度回传的。在计算图构建中如果需要经过all_gather操作后,仍需要将梯度回传给各个进程中的allgather前的对应变量,则需要重新继承torch.autograd.Function

https://pytorch.org/docs/stable/autograd.html 中对torch.autograd.Function进行了介绍

https://pytorch.org/docs/stable/notes/extending.html#extending-torch-autograd 中举例介绍如何重新实现其子类

 下面代码是为了说明all_gather相关特性及如何实现梯度回传.

\(x,y,z\)都是2x2矩阵,其之间关系为\(y=x+2, z=y*y\)

接下来就需要MPI进行进程间数据传递,将z进行汇总到每个进程即all_gather操作。然后将汇总的矩阵进行相乘,然后求均值。

r对y的导数如下:

\(r=0.25({}_{g_0}y_{11}^2*{}_{g_1}y_{11}^2+{}_{g_0}y_{12}^2*{}_{g_1}y_{12}^2+
{}_{g_0}y_{21}^2*{}_{g_1}y_{21}^2+
{}_{g_0}y_{22}^2*{}_{g_1}y_{22}^2)\)

\(\frac{dr}{d{}_{g_0}y}=
\begin{Bmatrix}
0.5{}_{g_0}y_{11}*{}_{g_1}y_{11}^2 & 0.5{}_{g_0}y_{12}*{}_{g_1}y_{12}^2 \\
0.5{}_{g_0}y_{21}*{}_{g_1}y_{21}^2 & 0.5{}_{g_0}y_{22}*{}_{g_1}y_{22}^2)
\end{Bmatrix}\)

gpu0上x值为\(\begin{Bmatrix} 1 & 1 \\1 & 1 \end{Bmatrix}\),gpu1上x值为\(\begin{Bmatrix} 0 & 0 \\0 & 0 \end{Bmatrix}\).通过公式可以计算出,r关于gpu0上的y的导数为\(\begin{Bmatrix}6 & 6 \\6 & 6\end{Bmatrix}\),r关于gpu1上的y的导数为\(\begin{Bmatrix}9 & 9 \\9 & 9\end{Bmatrix}\)

import os
import torch
from torch import nn
import sys
sys.path.append('./')
import torch.distributed as dist
from torch.autograd import Variable
from utils import GatherLayer def test():
#torch.manual_seed(0)
torch.backends.cudnn.deterministic=True
torch.backends.cudnn.benchmark=True
dist.init_process_group(backend="nccl", init_method="env://")
rank = dist.get_rank()
local_rank = int(os.environ.get('LOCAL_RANK', 0))
world_size = dist.get_world_size()
torch.cuda.set_device(local_rank)
print('world_size: {}, rank: {}, local_rank: {}'.format(world_size, rank, local_rank)) if local_rank == 0:
x = Variable(torch.ones(2, 2), requires_grad=True).cuda()
else:
x = Variable(torch.zeros(2, 2), requires_grad=True).cuda()
y = x + 2
y.retain_grad()
z = y * y z_gather = [torch.zeros_like(z) for _ in range(world_size)]
dist.all_gather(z_gather, z)
#z_gather = GatherLayer.apply(z)
r = z_gather[0] * z_gather[1] out = r.mean()
out.backward()
if local_rank == 0:
print('rank:0', y.grad)
else:
print('rank:1', y.grad)

(1)上述述代码中,先使用pytorch中提供的all_gather操作,运行代码会提示错误。错误信息如下:

Traceback (most recent call last):
File "test/test_all_gather.py", line 46, in <module>
Traceback (most recent call last):
File "test/test_all_gather.py", line 46, in <module>
test()
File "test/test_all_gather.py", line 36, in test
out.backward()
File "/usr/local/lib/python3.6/dist-packages/torch/tensor.py", line 185, in backward
torch.autograd.backward(self, gradient, retain_graph, create_graph)
File "/usr/local/lib/python3.6/dist-packages/torch/autograd/__init__.py", line 127, in backward
allow_unreachable=True) # allow_unreachable flag
RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
test()

(2)参考https://github.com/Spijkervet/SimCLR/blob/master/simclr/modules/gather.py, 该函数就是继承torch.autograd.Function,实现了all_gather后,梯度也能回传。

上述代码,启用z_gather = GatherLayer.apply(z),就实现了梯度回传功能,打印对变量y的梯度

world_size: 2, rank: 0, local_rank: 0
world_size: 2, rank: 1, local_rank: 1
rank:0 tensor([[6., 6.],
[6., 6.]], device='cuda:0')
rank:1 tensor([[9., 9.],
[9., 9.]], device='cuda:1')

GatherLayer类实现如下:

class GatherLayer(torch.autograd.Function):
"""Gather tensors from all process, supporting backward propagation.""" @staticmethod
def forward(ctx, input):
ctx.save_for_backward(input)
output = [torch.zeros_like(input) for _ in range(dist.get_world_size())]
dist.all_gather(output, input)
return tuple(output) @staticmethod
def backward(ctx, *grads):
(input,) = ctx.saved_tensors
grad_out = torch.zeros_like(input)
grad_out[:] = grads[dist.get_rank()]
return grad_out

下面网址有关all gather梯度传播的讨论

https://discuss.pytorch.org/t/will-dist-all-gather-break-the-auto-gradient-graph/47350

大规模人脸分类—allgather操作(1)的更多相关文章

  1. 用深度学习(CNN RNN Attention)解决大规模文本分类问题 - 综述和实践

    https://zhuanlan.zhihu.com/p/25928551 近来在同时做一个应用深度学习解决淘宝商品的类目预测问题的项目,恰好硕士毕业时论文题目便是文本分类问题,趁此机会总结下文本分类 ...

  2. [转] 用深度学习(CNN RNN Attention)解决大规模文本分类问题 - 综述和实践

    转自知乎上看到的一篇很棒的文章:用深度学习(CNN RNN Attention)解决大规模文本分类问题 - 综述和实践 近来在同时做一个应用深度学习解决淘宝商品的类目预测问题的项目,恰好硕士毕业时论文 ...

  3. 用keras的cnn做人脸分类

    keras介绍 Keras是一个简约,高度模块化的神经网络库.采用Python / Theano开发. 使用Keras如果你需要一个深度学习库: 可以很容易和快速实现原型(通过总模块化,极简主义,和可 ...

  4. wordpress搜索结果排除某个分类如何操作

    我们知道wordpress的搜索结果页search.php和分类页category.php是一样的,但是客户的网站是功能比较多的系统,有新闻又有产品,如果搜索结果只想展示产品要如何操作呢?随ytkah ...

  5. SQL分类-DDL_操作数据库_创建&查询

    SQL分类 1.DDL(Data Definition Language)数据定义语言 用来定义数据库对象:数据库,表,列等.关键字:create , drop, alter 等 2.DML(Data ...

  6. python集合的分类与操作

    如图: 集合的炒作分类: 确定大小 测试项的成员关系 遍历集合 获取一个字符串表示 测试相等性 连接两个集合 转换为另一种类型的集合 插入一项 删除一项 替换一项 访问或获取一项

  7. Python函数分类及操作

    为什么使用函数? 答:函数的返回值可以确切知道整个函数执行的结果   函数的定义:1.数学意义的函数:两个变量:自变量x和因变量y,二者的关系                      2.Pytho ...

  8. .NET做人脸识别并分类

    .NET做人脸识别并分类 在游乐场.玻璃天桥.滑雪场等娱乐场所,经常能看到有摄影师在拍照片,令这些经营者发愁的一件事就是照片太多了,客户在成千上万张照片中找到自己可不是件容易的事.在一次游玩等活动或家 ...

  9. face recognition[翻译][深度学习理解人脸]

    本文译自<Deep learning for understanding faces: Machines may be just as good, or better, than humans& ...

  10. face recognition[翻译][深度人脸识别:综述]

    这里翻译下<Deep face recognition: a survey v4>. 1 引言 由于它的非侵入性和自然特征,人脸识别已经成为身份识别中重要的生物认证技术,也已经应用到许多领 ...

随机推荐

  1. 2022-05-10内部群每日三题-清辉PMP

    1.项目经理管理的一个项目不断面临挑战.发起人经常无法做出决定,存在大量预算超支,团队成员不断从项目离职,高级管理层没有提供实际的支持.项目经理应该怎么做? A.与团队一起开会,以确定造成这些问题的原 ...

  2. Java使用RestTemplate发送Post请求时携带参数

    String url = "https://www.baidu.com"; HttpHeaders headers = new HttpHeaders(); //设置请求头,自己从 ...

  3. ubuntu配置phpmyadmin

    之前已经把LNMP环境搭建好了 安装: sudo apt-get install phpmyadmin 安装必要依赖 sudo apt-get install php-mbstring sudo ap ...

  4. 072_关于Dataloader导入Record的创建时间及修改时间并允许owner是Inactive

    1.在User interface 中 启用 Enable "Set Audit Fields upon Record Creation" and "Update Rec ...

  5. 关于ie浏览器query ajax提交单个操作无效

    第一次写博客 大家不要喷我!!!! 需求需要开发一个无刷新的用户注销和恢复注销功能 遇到的实际问题直接贴图----> 这是开始页面 当点击红xx时提示修改成功 这里似乎是对的哈 但是等点击刷新的 ...

  6. csv文件导入数据库中文乱码

    在向数据库的表中导入csv数据时,出现了中文乱码的问题,解决办法是在选择编码格式时选择10008 (MAC - Simplified Chinese GB 2312)即可

  7. Log4net使用探究

    第一步: 通过Nuget package 搜索Apache Log4net安装 第二步: 在项目Global.asax文件中添加读取 配置文件 第三步: 编写Loghelper 文件 1 public ...

  8. 15. 测试环境部署-linux

    抽奖项目部署文档: 1.抽奖项目使用python3开发,python版本3.x都可以 需要安装的python第三方模块 pip install django==1.9.0 这个一定要加版本号 pip ...

  9. Kubernetes--Pod生命周期中的重要行为

    Pod生命周期中的重要行为 除了创建应用容器(主容器及其辅助容器)之外,用户还可以为Pod对象定义其生命周期中的多种行为,如初始化容器.存活性探测及就绪性探测等. 初始化容器 初始化容器 (init ...

  10. OL3-Cesium 二三维鼠标事件统一处理

    like the github issue: https://github.com/openlayers/ol3-cesium/issues/344#issuecomment-214098148 th ...