Consistent 与 Mirrored 视角
Consistent 与 Mirrored 视角
在进行分布式训练时,OneFlow 框架提供了两种角度看待数据与模型的关系,被称作 consistent 视角与 mirrored 视角。
本文将介绍:
- 数据并行与模型并行的区别及适用场景
- 在分布式任务中采用 mirrored 视角及其特点
- 在分布式任务中采用 consistent 视角及其特点
数据并行与模型并行
为了更好地理解 OneFlow 中的 consistent 和 mirrored 视角,需要了解分布式任务中的 数据并行 、模型并行 两种并行方式的区别。
为了更直观地展示两者的差别,先看一个简单的 Op :矩阵乘法。
假定在模型训练中,存在一个输入矩阵 I ,通过矩阵 I 与矩阵 W 做矩阵乘法,得到输出矩阵 O 。
如以上所示,I的大小为(N, C1),W的大小为(C1, C2),O的大小为(N, C2)。
结合机器学习的业务逻辑,可以赋予以上几个矩阵直观意义:
- I 矩阵作为输入矩阵,每一行都是一个样本,一行中的各列代表了样本的特征
- W 矩阵代表了模型参数
- O 是预测结果或者 label ,如果是预测作业,那么就是由 I、W 求解 O,得到分类结果的过程;如果是训练作业,那么就是由 I 与 O 求解 W 的过程
当以上 I 矩阵的行 N 很大,说明样本很多;如果 W 矩阵的列 C2 很大,说明模型复杂;当样本数目、模型复杂程度复杂到一定程度时,单机单卡的硬件条件已经无法承载训练作业,就需要考虑分布式的方式训练。而在分布式系统中,可以选择 数据并行 和 模型并行。
为了便于理解数据并行与模型并行,先用下图作为矩阵相乘 Op 的示例:
等式左边第1个灰色的矩阵代表输入样本,每一行是一个样本;等式左边第2个蓝色的矩阵代表模型。
在后文中,将看到以上的 op,在数据并行与模型并行下,不同的“切分”方式。
数据并行图示
在 数据并行 中,将样本数据进行切分,切分后的数据 被送至各个训练节点,与 完整的模型 进行运算,最后将多个节点的信息进行合并,如下图所示:
模型并行图示
在 模型并行 中,将模型进行切分,完整的数据 被送至各个训练节点,与 切分后的模型 进行运算,最后将多个节点的运算结果合并,如下图所示:
总之:
- 数据并行下,各个训练节点的模型是完全一样的,数据被切分;
- 模型并行下,各个训练节点都接收一样的完整数据, 模型被切分。
接下来将介绍 OneFlow 看待分布式系统的两种视角(mirrored 视角与 consistent 视角),学习在不同的视角下如何选择并行方式。
两类占位符
在使用OneFlow搭建神经网络及定义与调用作业函数中已经介绍了 数据占位符 与 Blob 的概念。
实际上,针对并行,OneFlow的数据占位符还可以细分为 两类:分别通过接口 oneflow.typing.Numpy.Placeholder 和 oneflow.typing.ListNumpy.Placeholder 构造的占位符,分别对应 Consistent 与 Mirrored情况。
将在下文中看到具体应用。
在 OneFlow 中使用 mirrored 视角
其它的框架,如 TensorFlow、Pytorch 均支持 mirroed view;OneFlow 的 mirrored 视角与它们类似。
在 mirrored 视角下,模型被镜像复制到每张卡上,每个节点的模型构图是完全相同的,只能采用 数据并行 。
在 OneFlow 中,默认不是 mirrored 策略,需要通过 flow.function_config() 的 default_logical_view 接口来显式指定:
func_config = flow.function_config()
func_config.default_logical_view(flow.scope.mirrored_view())
在 mirrored_view 下,只能采用 数据并行 的并行模式,在调用作业函数时,需要将数据按照训练节点的数目(显卡总数)进行平均切分,并将切分后的数据放入 list 中进行传递,list 中的每个元素,就是后分配给 各个显卡 的实际数据。
训练函数的返回值类型,也变作了 oneflow.typing.ListNumpy,是一个 list, list 中的每个元素,对应了每张卡上训练结果。
以上提及的 list 中的所有元素 拼接在一起 ,才是一个完整的 BATCH。
代码
在以下的脚本中,使用采用 mirrored_view 视角,使用2个 GPU 进行训练。
重点部分的说明请见后文“代码解析”部分。
代码解读
以上代码中:
- 使用 flow.config.gpu_device_num 设置 GPU 数目为2
flow.config.gpu_device_num(2)
- oneflow.typing.ListNumpy.Placeholder 定义的样本数目,是被切分后的数目,即代码中的 BATCH_SIZE_PER_GPU 与总样本数 BATCH_SIZE 的关系为:BATCH_SIZE=BATCH_SIZE_PER_GPU×GPU_NUM
- def train_job(
- images: tp.ListNumpy.Placeholder((BATCH_SIZE_PER_GPU, 1, 28, 28), dtype=flow.float),
- labels: tp.ListNumpy.Placeholder((BATCH_SIZE_PER_GPU,), dtype=flow.int32),
- ) -> tp.ListNumpy:
- 切分后的数据,需要保存至 list 中传入训练函数;list 中元素的个数与 参与训练的GPU数目 一致;OneFlow 将按照 list 中元素顺序,向各卡传递数据( list 中第 i 个元素对应第 i 张卡):
- images1 = images[:BATCH_SIZE_PER_GPU]
- images2 = images[BATCH_SIZE_PER_GPU:]
- labels1 = labels[:BATCH_SIZE_PER_GPU]
- labels2 = labels[BATCH_SIZE_PER_GPU:]
- imgs_list = [images1, images2]
- labels_list = [labels1, labels2]
- loss = train_job(imgs_list, labels_list)
- 返回的得到的结果 loss,是一个 list,该 list 中元素个数与 参与训练的GPU数目 一致;list 中的第i个元素对应了第 i 张 GPU 卡上的运算结果。做了拼接后,计算并打印了 total_loss
- total_loss = np.array([*loss[0], *loss[1]])
- if i % 20 == 0:
- print(total_loss.mean())
在 OneFlow 中使用 consistent 视角
已经了解了 mirrored 视角,知道在 mirrored_view 视角下,样本会被平均分配到多个完全一样的模型上进行分布式训练,各个训练节点上的结果,需要组装才能得到真正完整的 BATCH,对应了逻辑上的 op 与 Blob。
除了 mirrored 视角外,OneFlow 还提供了 consistent 视角。consistent 视角是 OneFlow 的一大特色,与 mirrored 视角相比有很大的优势。
默认情况下 OneFlow 采取的是 consistent 视角,如果想显式声明,也可以通过代码设置:
config = flow.function_config()
config.default_logical_view(flow.scope.consistent_view())
之所以说 consistent 视角是 OneFlow 的一大特色,是因为在 OneFlow 的设计中,若采用 consistent_view,那么从用户的视角看,分布式系统中的多个设备将获得 逻辑上的统一,同样以本文开头的矩阵乘法为例,只需要关注矩阵乘法本身数学计算上的意义;而在工程上到底如何配置、采用模型并行还是数据并行等细节问题,可以使用 OneFlow 的接口轻松完成。OneFlow 内部会高效可靠地解决 数据并行中的数据切分 、模型并行中的模型切分 、串行逻辑 等问题。
在 OneFlow 的 consistent 视角下,可以自由选择模型并行、数据并行、流水并行或者混合并行。
代码
以下脚本,采用 consistent 视角,使用2个 GPU 进行训练,consistent 策略下默认的并行方式仍然是 数据并行。关于如何在 consistent 策略下设置 模型并行 及 混合并行 不在本文讨论范围,在OneFlow 的并行特色中有专门的介绍与示例。
代码中的重点将在下文介绍。
代码解读
以上代码中:
- 使用 flow.config.gpu_device_num 设置GPU数目:
- flow.config.gpu_device_num(2)
- 使用 tp.Numpy.Placeholder 定义 consistent 视角下的占位符,因为 Numpy.Placeholder 产出的 Blob 代表逻辑上的 op 及数据占位符,因此此处的 BATCH_SIZE 就是整个分布式训练的样本总和,不需要人为切分或者组合
- @flow.global_function(type="train")
- def train_job(
- images: tp.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),
- labels: tp.Numpy.Placeholder((BATCH_SIZE,), dtype=flow.int32),
- ) -> tp.Numpy:
- 调用作业函数,直接得到训练结果,训练结果已经由 OneFlow 完成分布式过程中切分与合并的工作。在 consistent 视角下,多卡的分布式训练与单卡的训练,代码差别极少,上手体验几乎一样
- for i, (images, labels) in enumerate(zip(train_images, train_labels)):
- loss = train_job(images, labels)
- if i % 20 == 0:
- print(loss.mean())
扩展
随着机器学习理论与实践发展,现在已经出现了很多单机无法训练的网络;也出现了越来越多仅采用数据并行无法很好完成训练的模型。
采用 OneFlow 的 consistent 视角,通过自由选择及组合并行方式,可以很好地解决以上问题,在 OneFlow 的并行特色进行了专门的介绍。
Consistent 与 Mirrored 视角的更多相关文章
- OneFlow 并行特色
OneFlow 并行特色 在 Consistent 与 Mirrored 视角中,已经知道 OneFlow 提供了 mirrored 与 consistent 两种看待分布式系统的视角,并且提前知道了 ...
- 不一样视角的Glide剖析
推荐阅读: 滴滴Booster移动App质量优化框架-学习之旅 一 Android 模块Api化演练 不一样视角的Glide剖析(一) Glide是一个快速高效的Android图片加载库,注重于平滑的 ...
- 【CSS进阶】试试酷炫的 3D 视角
写这篇文章的缘由是因为看到了这个页面: 戳我看看(移动端页面,使用模拟器观看) 运用 CSS3 完成的 3D 视角,虽然有一些晕3D,但是使人置身于其中的交互体验感觉非常棒,运用在移动端制作一些 H5 ...
- 如何在ASP.NET Web站点中统一页面布局[Creating a Consistent Layout in ASP.NET Web Pages(Razor) Sites]
如何在ASP.NET Web站点中统一页面布局[Creating a Consistent Layout in ASP.NET Web Pages(Razor) Sites] 一.布局页面介绍[Abo ...
- 不懂前端的程序员不是好美工——UI框架metronic使用教程——程序员视角
本着不懂前端的程序员不是好美工的观点,所以作为一个仅懂一点前端的程序员,为了成为一个好美工,所以只能用些取巧的方法伪装一下. metronic一个基于bootstrap的响应式的后台管理平台的UI框架 ...
- if else 的妙用 —— 顾客视角
if (storedCash % 100 != 0) { System.out.println("请输入100的倍数!!!"); } else if(storedCash % 10 ...
- 关于如何通过定义自己的CameraManager来控制视角
2016.8.30 发现了这个函数,可以直接获得摄像机的位置和旋转. Controller->GetPlayerViewPoint(CamLoc, CamRot); 最近看了几天PlayerCa ...
- Asp.Net Razor中的Consistent Layout
有意义的参考:http://www.asp.net/web-pages/tutorials/working-with-pages/3-creating-a-consistent-look Asp.ne ...
- Oculus中OVRPlayerController飞行视角的制作
最近项目上的事,忙的不可开交.忙里偷闲,记录下Oculus飞行视角的制作 师兄给我的要求是,带上Oculus,通过remote和头盔操作,可以完成飞行我的解决办法:1.消除重力的影响,如同在真空中,就 ...
随机推荐
- 【Springboot】Springboot监听器Demo
/** * @author: yq * @date: 2020/8/31 0:01 * @description 自定义事件 */ @Data public class MyEvent extends ...
- 病毒木马查杀实战第024篇:MBR病毒之编程解析引导区
前言 通过之前的学习,相信大家已经对磁盘的引导区有了充分的认识.但是我们之前的学习都是利用现成的工具来对引导区进行解析的,而对于一名反病毒工程师而言,不单单需要有扎实的逆向分析功底,同时也需要有很强的 ...
- 设计模式-UML图简单介绍
直接上法宝: 1.类(Class) 类图分三层: 第一层显示类的名称,如果是抽象类,则就用斜体显示. 第二层是类的特性,通常就是字段和属性. 第三层是类的操作,通常是方 ...
- 无线网络的加密方式:WEP、WPA和WPA2
目录 有线等效加密( WEP ) Wi-Fi 访问保护( WPA ) Wi-Fi 访问保护 II( WPA2 ) WPA-PSK/WPA2-PSK 无线网标准 有线等效加密( WEP ) 有线等效保密 ...
- Windows核心编程 第十四章 虚拟内存
第1 4章 虚 拟 内 存 <这一章没啥,是说的几个内存相关的函数 > 14.1 系统信息 许多操作系统的值是根据主机而定的,比如页面的大小,分配粒度的大小等.这些值决不应该用硬编码的形式 ...
- SpringBoot面向切面编程(AOP)
Aspect (与SpringBoot整合) 总结 作用位置 try{ try{ @Around 前置环绕通知 @Before 前置通知 method.invoke(..); }catch(){ @A ...
- 月薪6K和月薪2W的测试,有什么区别?
之前,我收到了一位朋友的好消息,说自己拿到了接近月薪 20k 的 offer. 说实话,软件测试岗位前期门槛低,但是想要拿到高薪真没那么简单.工作 2-3 年薪资还在原地打转的同学,都大有人在. ...
- 大学四年因为分享了这些软件测试常用软件,我成了别人眼中的(lei)大神(feng)!
依稀记得,毕业那天,我们辅导员发给我毕业证的时候对我说"你可是咱们系的风云人物啊",哎呀,别提当时多开心啦????,嗯,我们辅导员是所有辅导员中最漂亮的一个,真的???? 不过,辅 ...
- JAVA8 lambda表达式权威教程!
Java 8新特性----Stream流 jdk8是Java 语言开发的一个主要版本,它支持函数式编程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等等.今天就重点介 ...
- mysql整型后面的()宽度
int(5)这个5表示显示宽度 如果超出宽度则正常显示,所以人为指定显示宽度意义不大