1. 概述

在AI芯片领域,当前阶段NVIDIA基本上可以说是处于绝对的垄断地位,除了自身产品确实够强悍之外,最厉害的地方是还能借助CUDA生态令无数的开发者、研究人员都在为他家免费打工,从而将其市值推上3万亿美元。国内AI芯片厂家只要能达到其1%的市值就是300多亿美元即2000多亿人民币,这样作为一家芯片公司相信就已经很成功了,而且当前老美对国内的各种政策利好,在这样的大势下,只要走对路线相信还是能成功的。

国内各家AI芯片厂家苦CUDA久已,要么自个实力足够强大试图重建自家的生态,要么试图全兼容或半兼容CUDA生态,但是实际上效果都不大好,用户抱怨难用的不少,急眼了来一句:“咱们能不能好好学CUDA?”。问题即是机会,国产化Ai芯片生态的构建也是个持久战问题,因此本文对国产化Ai芯片生态做了一些思考,另外存在决定意识,我所讲的都是我一家之言,不一定看的全、看的对。

2. CUDA生态分析

伟人告诉我们做事情之前要先调查研究,如下图所示,我们把CUDA的生态一层层从上往下拆解开来进行分析。

image-1

2.1 应用层

首先是应用层,这一层是各种模型应用,是NVIDIA公司外的CUDA生态,是无数深度学习研究人员、开发者用户、客户围绕CUDA自发构建成的生态,这也是CUDA最牢靠最大的护城河,人员无数,这些应用也是离价值最近的最直接的生产力。

下面举例说明一些实际应用场景[2]:

  1. 大模型

    • 自然语言处理:如GPT-3、BERT等,用于文本生成、翻译、摘要、情感分析等。
    • 图像识别:如ResNet、Inception等,用于图像分类、目标检测、图像分割等。
  2. AIGC

    • 文本生成:自动生成新闻文章、小说、诗歌等。
    • 音乐创作:AI作曲家可以创作独特的音乐旋律和和声。
    • 艺术创作:AI艺术家可以创作绘画、雕塑等艺术作品。
  3. 多模态

    • 视觉问答:结合视觉和语言信息,回答关于图像内容的问题。
    • 多模态情感分析:分析文本、语音和面部表情等多个模态的情感状态。
  4. 文生图

    • 图像生成:根据文本描述生成相应的图像,如“一个阳光明媚的海滩”。
    • 漫画生成:根据剧本自动生成漫画页面。
  5. 图生图

    • 风格迁移:将一种艺术风格应用到另一张图片上,如将梵高的画风应用到现代照片上。
    • 图像编辑:通过图像到图像的转换,实现图像的自动编辑和美化。
  6. 文生视频

    • 视频生成:根据文本描述生成视频内容,如“一个在森林中奔跑的鹿”。
    • 视频摘要:自动从长视频中提取关键片段,生成简短的视频摘要。

具体应用举例[2]:

  • 教育

    • 使用AIGC生成个性化学习材料和练习题。
    • 利用多模态技术辅助语言学习,通过图像和声音增强记忆。
  • 娱乐

    • 使用文生图技术生成电影海报或游戏角色设计。
    • 利用图生图技术进行角色形象的自动设计和风格转换。
  • 医疗

    • 利用大模型进行疾病诊断和预测,辅助医生做出更准确的判断。
    • 使用多模态技术结合患者的医疗影像和临床数据进行综合分析。
  • 电商

    • 通过文生图技术生成商品的个性化展示图。
    • 使用图生图技术优化商品图片,提升视觉吸引力。
  • 新闻媒体

    • 利用AIGC自动生成新闻报道和文章。
    • 使用文生视频技术生成新闻摘要视频,快速传达信息。
  • 广告

    • 利用文生图技术生成广告创意和视觉素材。
    • 使用图生图技术优化广告图像,提升广告效果。

这些技术的应用正在不断扩展,未来可能会有更多创新和突破,而且这些应用绝大多数都是基于CUDA的基础设施进行开发的,无数的应用,无数的开发人员构建了NVIDIA CUDA 最牢靠的护城河。

2.2 框架层

这一层是深度学习框架,也是NVIDIA公司之外的CUDA生态,到这层就属于基础设施软件层了,这些工具主要与深度学习的训练、微调与推理框架相关,下面是它们各自的用途和特点[2]:

  1. DeepSpeed: 这是一个由微软推出的深度学习优化库,旨在帮助研究人员和开发人员加速大规模深度学习训练。DeepSpeed 提供了多种优化技术,如模型并行、梯度累积、混合精度训练等;

  2. Megatron-LM: 这是NVIDIA推出的一个用于训练大型语言模型的库。它利用了NVIDIA的GPU和NVLink技术来加速多GPU训练,使得训练非常大的语言模型成为可能;

  3. Flash-Attention: 这是一个用于提高注意力机制效率的库,特别是在Transformer模型中。Flash-Attention 通过优化内存访问和计算流程,显著提高了注意力层的计算速度与性能;

  4. Transformer Engine: 这是一个用于构建和训练Transformer模型的框架,它提供了一套丰富的API来简化模型的构建、训练和部署过程;

  5. Apex: 这是NVIDIA推出的一个PyTorch扩展,它提供了多种用于提升PyTorch性能的工具,包括混合精度训练、分布式训练等;

  6. PyTorch: 这是一个广泛使用的开源机器学习库,特别适合于深度学习和自然语言处理。PyTorch以其易用性、灵活性和动态计算图而闻名;

  7. VLLM: vLLM是一个由加州大学伯克利分校的LMSYS组织开源的大型语言模型(LLM)高速推理框架。它旨在提供快速、易用且成本效益高的LLM服务,特别是在实时场景下,可以显著提升语言模型服务的吞吐量和内存使用效率;

  8. TensorRT-LLM: 这可能是一个结合了NVIDIA的TensorRT优化库和大型语言模型(LLM)的框架。TensorRT是一个深度学习推理引擎,它可以将训练好的模型优化为高效的推理格式,以加速在生产环境中的模型部署。如果TensorRT-LLM存在,它可能是为了在NVIDIA硬件上优化和加速大型语言模型的推理;

  9. Hugging Face: 是一个专注于自然语言处理(NLP)的开源社区和公司,提供了一系列的工具和库,以促进机器学习模型的共享和应用。包括TGI, transformers, accelerate, diffusers, peft等。

除了目前以上这些比较主流的工具之外,而且随着技术的发展,新的工具和库可能会不断出现。这一层构成了NVIDIA CUDA 的框架与开发库护城河。

2.3 CUDA 加速库与编译器层

CUDA加速库以及编译器再加上周边的辅助工具,构建成了整个NVIDIA CUDA Toolkit系统。CUDA Toolkit是NVIDIA自建闭源生态,是一个全面的开发环境,用于创建高性能、GPU加速的程序,以下是CUDA Toolkit的主要特点和功能[2]:

  1. 开发环境
    • CUDA Toolkit提供了一个完整的开发环境,支持在GPU加速的嵌入式系统、桌面工作站、企业数据中心、云平台和超级计算机上开发、优化和部署应用程序;
  2. GPU加速库
    • 包括cuDNN(深度学习神经网络库),cuBLAS(基本线性代数子程序的实现)、cuFFT(快速傅里叶变换库)、cuRAND(随机数生成库)、cuSOLVER(线性代数求解库)、cuSPARSE(稀疏矩阵处理库)等,这些库可以显著加速科学计算和数据处理任务;
  3. 编译器和运行时库
    • 包含NVCC编译器,用于编译CUDA程序,以及运行时库,用于在不同平台上部署应用程序;
  4. 调试和优化工具
    • 提供了NVIDIA Nsight Compute和NVIDIA Nsight Systems等开发工具,帮助开发者优化和提高应用程序的性能;
  5. 多GPU配置
    • 内置功能支持在多GPU配置中分布计算,使得应用程序可以从单GPU工作站扩展到拥有数千GPU的云安装;
  6. 新架构支持
    • CUDA 12引入了对NVIDIA Hopper和Ada Lovelace架构的支持,包括下一代Tensor Cores、Transformer Engine、NVLink Switch、混合精度模式、第二代多实例GPU(MIG)等;
  7. 异构内存管理(HMM)
    • 支持在主机内存和加速器设备之间无缝共享数据,而无需由CUDA分配或管理内存,简化了应用程序的移植和使用外部框架;
  8. 安全功能
    • 支持Hopper GPU的机密计算(Confidential Computing),提供加密和身份验证功能,保护用户代码和数据;
  9. 文档和培训
    • 提供详细的技术文档和培训课程,帮助开发者更好地理解和使用CUDA Toolkit。

通过这些功能,CUDA Toolkit为开发者提供了强大的工具和资源,以实现高效的GPU编程和加速计算。CUDA TOOLKIT 构成了NVIDIA GPU基础软件护城河。

2.4 NVIDIA云原生软件栈

NVIDIA Cloud Native Stack 是一套软件集合,用于在 NVIDIA GPU 上运行云原生工作负载。它基于 Ubuntu、Kubernetes、Helm 以及 NVIDIA GPU 和网络运营商构建而成。以下是其主要特点和组件[2]:

  1. 平台支持:适用于各种用例和行业的应用开发和部署,包括高性能计算、对话式 AI、推荐系统等 ;

  2. 灵活部署:可在裸金属服务器、Kubernetes 或虚拟化环境中运行,支持本地、云端和边缘部署,以最大化利用 GPU 资源并提高应用的便携性和可扩展性 ;

  3. AI 软件套件:NVIDIA AI Enterprise 是一个端到端的云原生 AI 软件套件,助力组织提高运营效率并解决新问题 ;

  4. 容器化:NGC 目录托管了经过 NVIDIA 优化的 AI 和数据科学软件容器,简化了部署流程 ;

  5. 预训练模型:NGC 目录提供预训练的 GPU 优化模型,适用于多种 AI 任务,可以按原样使用或重新训练 ;

  6. Helm 部署:实现 Kubernetes 集群上的软件部署自动化,NGC 目录提供支持 Kubernetes 的 Helm 部署 ;

  7. NVIDIA GPU Operator:一个由 NVIDIA 驱动的套件,包含容器运行时、设备插件和管理软件;

  8. Ansible Playbooks:提供自动化安装、升级、验证和卸载 NVIDIA Cloud Native Stack 的 Ansible 剧本 ;

  9. 监控和存储:支持在 Cloud Native Stack 上部署 Prometheus/Grafana 和 Elastic Logging 栈进行监控,以及 Local Path 和 NFS 存储提供程序 ;

  10. 版本控制:Cloud Native Stack 支持生命周期管理,允许用户升级至下一个可用版本 ;

  11. 组件矩阵:详细列出了不同版本和发行日期的 Cloud Native Stack 组件,包括操作系统、容器运行时、Kubernetes、Helm、NVIDIA GPU 运营商和网络运营商等 ;

  12. NVIDIA LaunchPad:提供预先配置的环境,以便用户快速开始使用 。

NVIDIA Cloud Native Stack 通过提供这些工具和特性,使得开发者和企业能够更容易地在云原生环境中利用 NVIDIA GPU 的强大计算能力。这一层主要还是K8S生态,工具都是开源的相对来说比较的开放,国内芯片厂家只要老老实实的参考nvidia cloud native stack 进行开发即可。

3.破局策略

3.1 统一认识

国产AI芯片生态上要能破局首先是要统一认识,认识是行动的指导。NVIDIA的CUDA生态链是非常的强大,但是通过以上分析可知真正的强大在应用层有无数的开发人员、研究人员在开发应用在做研究,框架层有很多的厂家在基于CUDA构建基础设施。如果剥离了这些,NVIDIA本身也只是一家普通的AI芯片公司,要破局并非不可能,因此国产AI芯片厂家要达成的认识的第一点是:国产AI芯片生态破局点在于CUDA TOOLKIT,而不是应用层与框架层。

问题即是机会,事物的内部矛盾是事物发展的根本动力。首先是要解放思想承认现实,实事求是的从客观实际出发,即不走速胜论路线也不走完全不可能路线,具体问题具体分析。从以用户为中心出发,而不是以技术为中心出发是国产AI芯片生态破局的根本之道。从用户出发,也是从人性出发,违背人性的技术走不远,既然从人性出发那么就需要考虑以下三不原则:

1)不要让用户学,学CPU编程、学CUDA编程已经学的够多的了,再学真学不动;

2)不要让用户想,无脑使用最好;

3)不要让用户烦,能简单点就简单点最好;

海能够纳百川是因为它足够的低,放低用户的开发、使用门槛,用户自然而然汇聚而来,当做到使用门槛比NVIDIA的 CUDA 门槛还要低时,新的生态自然而然形成。这是国产AI芯片厂家要达成的认识的第二点。

3.2 生态策略

下图是目前国内各AI芯片厂家的生态破局策略图,有完全自建生态的,有魔改框架组件的,有转换框架组件的,有基于开源开发的,下面的章节里我们一层层的解读这些策略。

image-2

3.2.1 应用层与框架层

通过第2章的分析可知,应用层与框架层是全世界的无数开发人员、无数研究人员以及无数厂家围绕CUDA TOOLKIT 构建的生态,没有一家厂家甚至国家有能力重构这样的生态,国内想重构这个应用生态的各厂内项目基本上都已经凉凉,自己去提供开发框架试图掌握上层应用生态的也基本半死不活。

对与应用层与框架层的破局策略是不要试图去改变无数开发者,去改变无数研究人员的使用习惯,更不可能让一些厂家转而使用自己的框架,而且人家又不是傻子,在巨大的利益面前,真没几人会愿意替别人做嫁衣,任何试图改变开发者、研究人员、各个应用厂家的行为都是属于主观不符合客观。

那么对于应用层与框架层如何破局应对? 建议是“打不过就加入”,对于存量的应用与框架,直接拉取无需做任何修改或者最多只改几行代码即可使用,遵循“不要让用户想,不要让用户烦,不要让用户学”,这样的三不原则。有些技术人员一听这个可能就会来喊一句:“这怎么可能?” ,其实只要对底层技术抽象的足够好是完全可以做到的。

3.2.2 CUDA TOOLKIT 层

CUDA TOOLKIT 层是被NVIDIA牢牢掌控的一层,这一层看上去是NVIDIA最为强大的护城河,但是恰恰相反,CUDA TOOLKIT 反而是NVIDIA最为薄弱的护城河,集中一家公司的力量在一定条件下就可以完成。对于这一层目前国内AI芯片厂家有以下几个破局路线:

1,完全自建类似CUDA的生态的,构建私有的xxDNN,xxFFT,xxBLAS,xxFFT等,再自我构建开源的框架层,再继续往上构建应用开发层,算法层等,投入巨大但是效果很一般。CUDA之所以能成为生态那是一开始根本就没人看好,也没有对手,属于天时、地利、人和三合一自己长出来的。目前在国内想重建CUDA生态也要看看其他厂家愿不愿意合作,国内各家AI芯片厂都在试图构建自己的生态,对同类生态资源多多少少都有挤占,谁也不想替别人做嫁衣,而且也要面对NVIDIA用户的粘性问题,所以这一条路线基本上没太大希望,具体例子可以参考某500强大厂;

2,魔改开源框架组件的,国内ai芯片厂家走这一类路线的也不少,自己开发类似CUDA toolkit这样的工具,然后魔改开源框架组件以及各种性能加速库。这一策略如果是应用在推理芯片路线,一定程度上还是可以的,推理的复杂度远远低于训练与微调,算子只要前向算子,只要集中力量自我开发一个推理框架再遍历支持几百个模型,在有限的资源下也是没问题的。但是如果客户想用自家的推理框架而不用厂家提供的,那么新的推理框架的适配工作量还是不少的。

魔改开源组件的好处是,往上是基本上可以不动应用层,不改变应用层的用户习惯,往下是内部的各种加速库,编译器甚至芯片都可以自己玩自己的,不太需要考虑协同设计,反正都是内部问题,都能跑的起来保证项目交付。缺点是每一个版本都难以迁移,不同代际芯片的软件栈难以无缝迁移,各种版本不兼容,然后算子库也都需要重写,比如要将flash-attention, deepspeed, transformerEngine,apex, pytorch等这些基础框架在XPU上支持起来,每一代的芯片都有海量的算子要重写,对公司资源的消耗是海量的,人力投入巨大,重复的海量工作严重延误芯片推向市场的时间,所以这一条路线有点像大块头无脑秀肌肉可能适合推理芯片但是真不适合训练芯片。

3,将CUDA源代码无缝翻译为XPU代码,这一路线国内AI芯片厂家也有,看上去是比较难而正确的路线,不改变应用层,也不改变框架层,同过转换与编译工具将框架层里的cuda源代码翻译为XPU代码进而编译出XPU可执行文件。这一条策略做到了“将复杂留给自己将简单留给用户”,对用户最为友好真正做到了遵循“不要让用户想,不要让用户烦,不要让用户学”这样的三不原则。但是缺点是对AI芯片厂家要求较高,需要加速库,编译器,硬件三者协同设计,并且如果本身芯片的演进路线与NVIDIA硬件不同,那么实现与兼容起来会比较的难受。所以建议的策略是先兼容已有的、普遍的、海量存量,再以特殊情况的策略对待增量,增量毕竟对公司的资源消耗会小点,先保证存量可用,快速推向市场抢占先机,再空出资源腾出手解决增量问题,即“先立再破”。这一策略需要顶层统一思想路线,软硬件协同设计。

这一策略具体实现方案举例如下:

1)应用层

应用层尽量做到不改任何代码用户直接拉取即可使用,实在不行最多一句import transfer_to_xpu

2)框架层

框架层采用monkey patching 策略完成cuda代码到xpu代码的转换,比如pytorch,megatron_lm, deepspeed, vllm, accelerate, transformers等尽量做到直接拉取即可使用,实在不行即提供transfer_to_xpu接口,供用户 import transfer_to_xpu完成调用。

3)算子层

算子层可以视情况提供将CUDA源代码直接编译为XPU二进制的编译工具,也可以提供对CUDA算子代码进行关键词替换或宏替换工具。

3)编程模型

遵循SISD, SIMT的编程思想,不要试图改变开发者用户的编程习惯,全面参考CUDA的线程编程模型,内存编程模型,IO编程模型以及异构执行编程模型。

4)编译器层

从人性懒惰出发,遵循SISD, SIMT的编程思想,将SISD, SIMT 代码在编译器层映射为SIMD 代码,从而提升不同代际产品算子的可移植性以及减少算子的编程学习成本。

5)硬件层

软硬件协同设计,启用SIMT+SIMD 架构支持编译器遵循SISD,SIMT的编程思想。

3.2.3 GPU云原生工具

这一层主要是K8S+GPU的生态,而且工具基本上也是开源的,只要遵循“不改变用户使用习惯”的原则,系统梳理全面复制即可完成GPU云原生生态兼容。

4. 小结

“让我痛苦的,必将使我强大!”,“克服自身现有的问题,才是成长最快的方式!”,这两句话用在国产化AI芯片生态兼容上也是合适的。”路虽远行则将至,事虽难做则必成,漫漫长路必见曙光!”,AI芯片关系到国家的竞争力,也与诸位一起共勉。

日拱一卒,功不唐捐,分享是最好的学习,与其跟随不如创新,希望这个知识点对大家有用。另作者能力与认知都有限,”我讲的,可能都是错的“,欢迎大家拍砖留念。

5. 作者简介

常平,为学,闻道,践行。

6. 参考资料

[1] https://www.changping.me

[2] https://kimi.moonshot.cn 生成

7. 版权申明

本文的版权协议为 CC-BY-NC-ND license:https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh

在遵循署名、非商业使用(以获利为准)以及禁止演绎的前提下可以自由阅读、分享、转发、复制、分发等。

1. 概述

对大模型进行张量并行或流水并行切分是个比较麻烦的工作,有些同学觉得这个过程比较麻烦,而采用取巧的策略选择绕开这个切分工作,选用将原生的,比如从huggingface下载的权重转为megatron格式,从而快速完成该大模型的预训练、微调或推理。

殊不知这一过程是从一个小坑掉到另外一个大坑: 先抛开模型转换对用户使用体验不大好的问题,格式转换的致命问题是会在一定概率下引起模型的准确率分数下降,从而造成推理结果的不一致。模型准确率分数的下降也会造成大模型在排行榜上的排名下降,因此,一些大模型厂家是不能接受这种行为的。

将所有的大模型权重都转为megatron gpt或其他格式也是一种一刀切的行为,没有考虑到各个模型的特殊性,以普遍打特殊也是违背这个世界的运行法则的一种行为,不是早上会出问题就是晚上会出问题。这里参考megatron的官方文档说明如下。

2. 模型转换与微调

megatron里微调一个大模型基本上可以分为以下几个步骤:

1)从huggingface下载大模型的权重;

2)使用大模型转换脚本将该权重从Huggingface格式转换为megatron格式;

3)基于这个转换后的权重设置微调参数,然后开始微调;

4)最后保存微调好的权重。

以LLama-2为例,将Llama 权重从huggingface下载下来,然后采用megatron自带的Llama-2 转换器转换为megatron格式,但是需要注意的是这一过程必须正确设置大模型的张量并行大小即TP参数,如下:

模型大小 张量并行大小(TP)
7B 1
13B 2
70B 8

基于TP值以及Llama-2 ${TOKENIZER_MODEL}路径,在megatron根目录下执行以下转换命令可以将Llama-2 权重从Huggingface格式转换为Megatron格式:

1
2
3
4
5
6
7
8
9
$python tools/checkpoint/convert.py \
--model-type GPT \
--loader llama2 \
--saver megatron \
--target-tensor-parallel-size ${TP} \
--checkpoint-type hf \
--load-dir ${HF_FORMAT_DIR} \
--save-dir ${MEGATRON_FORMAT_DIR} \
--tokenizer-model ${TOKENIZER_MODEL}

完成此转换后,可以将该权重采用megatron进行微调,微调结束后再保存该新的权重,然后这个权重就可以用于推理了。需要注意的是如果是只识别huggingface格式的推理工具则需要将该权重再转回huggingface格式才能用于推理。

3.模型准确率分数说明

下列表格列出了原生的Llama-2与转换后的LLama-2 推理结果的准确率比较。表格里的数值是megatron格式与原生格式之间的基准测试百分误差,计算公式为:”|<llama_score> - <megatron_score>| / <llama_score>”。在所有测试中(每种模型大小共80个),平均误差为0.15%。

经过分析,两种模型之间基准分数的微小差异是由于实现中的小的算术差异造成的,这些差异稍微改变了数值,影响这种差异的因素包括:

  • Megatron在几个地方执行批量矩阵乘法,例如在self attention 内部以及在SwiGLU中,而Llama分别执行这些操作;

  • Megatron在自注意力中使用torch.baddbmm,而Llama使用torch.matmul;

  • Megatron对旋转位置嵌入使用sin/cos实现,而Llama使用极坐标/复数实现;

  • Llama在初始化期间调用torch.set_default_dtype(torch.float16),而Megatron则不调用。

准确度分数比较说明见以下表格。

3.1 Big Bench

得分类型:多项选择成绩。

bigbench / standard 7b 13b 70b
date_understanding 0.29% 0.13% 0.12%
general_knowledge 0.00% 0.00% 0.00%
human_organs_senses 0.00% 0.00% 0.00%
intent_recognition 0.00% 0.11% 0.00%
riddle_sense 0.00% 0.00% 0.00%
similarities_abstraction 0.00% 0.58% 0.00%
simple_arithmetic_json_multiple_choice 0.00% 0.00% 0.00%
undo_permutation 0.19% 0.19% 0.18%

3.2 Multilingual

得分类型:多项选择成绩。

multilingual / xcopa 7b 13b 70b
en-template-mGPT-remove-punctuation 0.08% 0.00% 0.00%
et-template-mGPT-remove-punctuation 0.00% 0.13% 0.25%
ht-template-mGPT-remove-punctuation 0.26% 0.13% 0.26%
id-template-mGPT-remove-punctuation 0.11% 0.00% 0.19%
it-template-mGPT-remove-punctuation 0.00% 0.10% 0.09%
qu-template-mGPT-remove-punctuation 0.00% 0.00% 0.27%
sw-template-mGPT-remove-punctuation 0.14% 0.13% 0.13%
th-template-mGPT-remove-punctuation 0.25% 0.13% 0.13%
tr-template-mGPT-remove-punctuation 0.26% 0.00% 0.34%
vi-template-mGPT-remove-punctuation 0.00% 0.11% 0.00%
zh-template-mGPT-remove-punctuation 0.00% 0.10% 0.09%

3.3 LM Evaluation Harness

得分类型:多项选择成绩。

lm-eval 7b 13b 70b
boolq 0.04% 0.04% 0.07%
hellaswag 0.02% 0.03% 0.03%
piqa 0.00% 0.00% 0.07%
winogrande 0.00% 0.11% 0.20%

3.4 MMLU

得分类型:多项选择成绩。

注意:括号内的数字是每个大类中子任务的数量。

mmlu 7b 13b 70b
stem [18] 0.79% 0.05% 0.01%
humanities [13] 0.19% 0.01% 0.02%
other (business, health, misc.) [14] 0.08% 0.06% 0.12%
social sciences [12] 0.37% 0.21% 0.01%

以上数据可知,模型权重从huggingface格式转换为megatron格式会引起准确率的下降,虽然下降的不多,但是这一结果不是所有的用户都愿意接受的。

4. 小结

本文介绍了模型权重从huggingface格式转换为megatron格式进行训练所造成的影响,准确率只是模型质量的一个约束指标,从工程角度看 训练或微调的性能、收敛精度也是另外两个比较重要的约束指标。

日拱一卒,功不唐捐,分享是最好的学习,与其跟随不如创新,希望这个知识点对大家有用。另作者能力与认知都有限,”我讲的,可能都是错的“,欢迎大家拍砖留念。

5. 作者简介

常平,为学,闻道,践行。

6. 参考资料

[1] https://github.com/NVIDIA/Megatron-LM/blob/main/docs/llama2.md

7. 版权申明

本文的版权协议为 CC-BY-NC-ND license:https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh

在遵循署名、非商业使用(以获利为准)以及禁止演绎的前提下可以自由阅读、分享、转发、复制、分发等。

1. 易经、道德经、矛盾论都讲了什么

为学日益,闻道日损,一言以蔽之:易经:不变、简变、易变,理 、数 、象,阴阳辩证;道德经:道、德、无为、有无辩证;矛盾论:对立与统一,普遍与特殊,同一与斗争,矛盾辩证。

易经、道德经、矛盾论此三者也有共同点,即都在自己的时空内阐述了对辩证法的认识:阴阳辩证、有无辩证、矛盾辩证。

2. 易经在讲什么

《易经》认为世界是变化的,“生生之谓易”,“无极生太极、太极生两仪、两仪生四象、四象生八卦、八卦演化六十四卦、六十四卦又为末济”,如此循环。《易经》虽然是中国的万经之首,但是也有其时代局限限,比如各种卦象的演化已不大适合用于指导现今的工作与生活。然而其“三易三法则”讲述的是这个世界运行的本质,具备普世参考价值与意义。

2.1 三易 - 不变、简变、易变

《易经》里有三个原则,即“不易、简易、变易”,也可以称之为“不变,简变,易变”,当然这些变化的划分也是相对的。

不变,万事万物都在变化,但是变化的背后也有不变,或者说其变化周期超级长。道家称之为“道”, 佛家称之为“如来”,基督称之为“上帝”,数学称之为“公理”,物理学称之为“奇点”。这些即为”不变“。

简变,万事万物都在变化,变化的背后也有不变的道理,但不是所有的事物都是不变或者时刻在变化的,比如数学里的“定理”,律法的”法则“。事物在变化,但变化也是有差异的,比如地球自转一次24小时,地球绕太阳一周为一年,太阳系围绕银河系转一圈需要2.3亿年,如果将太阳围绕银河转一圈定义为不变,地球绕太阳一周可以定义为简变。在变化但是不是变化的那么快的事物,称之为”简变“。另外还有一个维度认为 ”简变“是复杂多样的时刻变化的事物的简化。

易变,这个世界是变化的,在这个时空中,没有一样东西是不变的,万事万物,思想、情况无时不刻都是在变化。这里的易变更多讲的是无时不刻不在变化的事物、表象,如同数学的各种从公理、定理演化出来的计算题目,题目千变万化,如果掌握不了公理、定理就应对不了各种变化多样的题目。人也是无时不刻不在变化的,人体的细胞在一年左右的时间里身体98%的细胞都会被重新更新一次,那么一年后的你还是那个“你”么?细胞无时不刻不在变化,但基因是不变的。

2.2 三法则 - 理 象 数

《易经》最为基本的三原则之后还有三法则:即理、象、数,我们可以理解成 事物背后不变的道,易变的表象以及用于度量的数据,每个事物到了一定的数就一定会变,从而产生新的象。

只要事物无时不刻不在变化就一定有它的不变的理,易变的象以及度量它的数。比如,在地球上往天空上抛的石头总是会落下,石头总是落下这背后是万有引力这个理,现象是石头落下,数是 落下来的速度、时间、加速度。

事物只要发生变化就有它的“理、象、数”。而且只要到了一定的“数”就一定会发生变化,从而产生新的“象”,这也是由它背后的那个“理”决定的。这个数 也是用于 “占”即推理的依据。人们常说做人不要太过分,也是这个道理,过犹不及。

2.3 阴阳辩证

“一阴一阳之谓道”。既有阴,又有阳,这就是道,这就是事物发展的规律。《易经》里阴阳是64卦的基础,如同计算机里的二进制。其告诉我们一个时空最基本的秘密:阴阳是构成万事万物最基本的元素。阴阳也是易经的朴素辩证法。阴阳辩证法具有几个特点:相生、相克、共存、转化、平衡。

阴阳相生,事物的阴阳两个方面是运动变化的,比如四季更迭,白天黑夜的变化,此进彼退,此消彼长;

阴阳相克,万事万物存在着对立的两个方面,比如冷热、福祸、高低、快慢、难易等;

阴阳共存,事物的两个方面都以对立的另一个方面作为自己存在的前提,互相共存,互相作用,不可独立存在,比如手心与手背,身体与影子,桌面桌背等;

阴阳互转,事物的阴阳两个方面并在在一定条件下也会发生相互转化最终达到新的平衡。比如,我们已知地球的白天黑夜更替是由地球自转而产生的,有白天就有黑夜,白天黑夜是共存的,比如南半球白天,北半球就黑夜,白天与黑夜在一定的条件下可以相互转化。有正离子就有负离子,再一定条件下正负离子也可以互相发生转化,最终达成新的平衡,共存于同一个物体内。

“潜龙勿用、见龙在田、终日乾乾、或跃在渊、飞龙在天、亢龙有悔”,也是一个相生相克相互转化的过程。

3. 道德经在讲什么

《道德经》概要来说主要讲了“道“,”德“, ”无为“, ”有无辩证“ 这四个方面。

3.1 道德

“有物混成,先天地生,寂兮寥兮,独立而不改,周行而不殆,可以为天地母。吾不知其名,字之曰道,强为之名曰大。”,“上德不德,是以有德;下德不失德,是以无德。”。

《道德经》里的道,指的是产生万物的不变规律,而德指的是万物生长的内在根据。道生万物,德养万物:“道生之,德畜之,物形之,势成之。是以万物莫不尊道,而贵德。”

“道,人之所蹈,使万物不知其所由;德,人之所得,使万物得其所欲。”,道是人应该遵循的规律,但是万事万物又不知道这个道是从哪来的,德是人之所得到的给养,是使万事万物能生养的基本欲求。“

3.2 无为

《道德经》里讲的无为,是个容易令人误解的地方,按现代文字面的意思就是啥都不做,躺平,比较消极。然而“法无定法”,躺平对一些人来说也不一定就是坏事。

按道家思想来说“无为”可以分为五层意思。即:天为、顺为、先为、疏为,勿为。

天为,无为的第一层意思是天为。“为学者日益,闻道者日损,损之又损,以至于无为,无为而无所不为。”,学习技能是日益,学习道要日损,逐步去掉人的“贪嗔痴慢疑”,剥离人为剩下的天为即为无为。这里的无为是按规律办事,主观要符合客观。

顺为,无为的第二层意思是顺为。顺势而为,“道生之,德畜之,物形之,势成之”,“上善若水”,水总是顺势而为的,这里的无为是顺为,要顺势而为。

先为,无为的第三层意思是先为。比如扁鹊他哥,扁鹊在与魏文王对话中告诉魏文王:“真正好的医生,早在病人还没有患病的时候,就能看出病人将要出现的问题。。。。”,这里的无为表达的是先为的意思,要具备预见能力,在事物刚出现苗头时就能预见到,先为之。

疏为,无为的第四层意思是疏为。到了这里面向的对象是掌握一定社会资源的人。”上德不德,是以有德;下德不失德,是以无德,上德无为而无以为;下德无为而有以为。“,上位者如果什么事都亲力亲为,有时候反而不好,要该亲为的时候亲为,不该亲为的时候不亲为,即疏为。事事亲为,容易打击下属的积极性。锻炼不了新人,培养不出新人,也容易导致后继无人。比如诸葛亮鞠躬精粹,事事亲为,把自己累死不说,还导致的一个后果是蜀国后继无人很快就亡国了。这里的无为也是在说,该放手就放手,该亲为就亲为,不要事事亲为,过犹不及。

勿为,无为的第5层意思是勿为。这一层也是面向掌握一定社会资源的人,如果是掌握较大的社会资源就不要妄为。比如 各朝亡国之君,到了这一层次,不瞎搞不乱折腾就是最好的”有为“。还比如这几年乱去炒A股,只要不炒A股,收益就是超过90%的人了。

3.3 有无辩证法

“无,名天地之始;有,名万物之母。故常无欲,以观其妙;常有欲,以观其徼。此两者同,出而异名。同谓之玄,玄之又玄,众妙之门。“,道生德养,道无德有,《道德经》里还有个非常重要的概念即”有、无“,体现了有无辩证法。有无辩证法具有几个特点:有无相同,有无相生、相互转化,有无平衡。

有无相同,“此二者同,出而异名”。杯子的周边是有,中间的空是。房子的周边是有,房间内部是无。车轱辘的轮子是有,轮子中间的轴孔是无。 ”有“提供价值,然后通过“无”发挥出这个价值。

有无相生,“故有无相生,难易相成,长短相形,高下相倾,音声相和,前后相随。” ,“祸兮福所倚;福兮祸所伏。孰知其极?”。有和无互相转化,难和易互相形成,长和短互相显现,高和下互相倾向,音与声互相相和,前和后互相跟随, 福祸互相倚伏 - 这些都是一定这样的。“曲则全,枉则直;洼则盈,弊则新;少则得,多则惑。。。。”,有时候委屈反而能是周全,弯腰反而能更好的站直。

有无相互转化。旧的有无可以在一定的条件下转化成新的有无。“反者道之动,弱者道之用。天下万物生于有,有生于无。” ,事物总是向相反的方向运动的,当违反道的规律时,道就动起来了。道有德无,有之以为利(价值),无之以为用(作用)。

4. 矛盾论

矛盾即对立统一,矛盾论里讲了一个最主要的内容即矛盾辩证法。矛盾辩证法里对立统一的观点是最核心的基本观点,其精髓是矛盾的普遍性与特殊性。

4.1 矛盾辩证法

4.1.1 对立与统一

矛盾就是对立统一,就是用对立统一的观点看问题,矛盾的对立统一规律告诉我们矛盾双方具备普遍性与特性性,同一性与斗争性的关系。

4.1.2 普遍性与特殊性

矛盾的普遍性是指”矛盾存在于一切事物中,存在于一切事物发展过程的始终,旧的矛盾解决了,新的矛盾又产生,事物始终在矛盾中运动。即“矛盾无处不在,矛盾无时不有”。矛盾的普遍性告诉我们事物是普遍矛盾存在的,问题也是普遍的,不同的人,不同的场景,不同的时空,矛盾都是普遍的。

矛盾的特殊性是矛盾分析法的核心所在,是”各种物质运动形式中的矛盾都带特殊性“。矛盾的特殊性告诉我们做事具体问题要具体分析。以普遍打特殊或者以特殊打普遍,都必然会出问题。这就要求我们工作中要注意具体问题具体分析,不搞一刀切。

普遍性与特殊性在一定的条件下也可以互相转化。

4.1.3 矛盾不平衡

矛盾的不平衡,是矛盾特殊性在不同阶段不同时期的表现。矛盾的不平衡,要求我们做事事既要坚持重点论,又要坚持两点论,要用“弹钢琴”的手法来做事,有重按键,有轻按键,还要每个键都兼顾到,这样弹出来的才是美妙的音律。

坚持两点论和重点论相统一, 要求我们做事既要抓住主要矛盾 同时也要兼顾次要矛盾,在工作中要抓重点带全局,稳定全局、重点突破、以点及面、梯度推进、波浪式前进。

按矛盾辩证法办事就是坚持两点论和重点论相统一,坚持两点论、两分法、一分为二,全面的观点看问题。

4.1.4 同一性和斗争性

同一性和斗争性,即统一性 与 对立性,双方是共存的。同一性和斗争性相互联结、相互制约。同一性离不开斗争性,没有斗争就没有同一,斗争性也离不开同一性,斗争性寓于同一性之中。同一性与斗争性在一定的条件下能互相转化。

5. 小结

本文简要讲述了易经、道德经、矛盾论的主要观点,并且简要比较了阴阳辩证法、有无辩证法、矛盾辩证法这三者的差异。为学日益,闻到日损,理论要能联系实际,要能用于指导实践才能发挥出其应有的价值。在阴阳辩证法,有无辩证法,矛盾辩证法中,矛盾辩证法最与时俱进,对工作实践最具备指导价值。另作者能力与认知都有限,”我讲的,可能都是错的“。

6. 作者简介

常平,中科大硕,某AI独角兽深度学习高级软件主管工程师、架构师,前EMC资深首席工程师,主要工作背景在深度学习、大数据、云计算、分布式中间件以及Linux内核领域。

7. 参考资料

[1] 《易经》

[2]《易经杂说》

[3] 《道德经》

[4] 《矛盾论》

8. 版权申明

本文的版权协议为 CC-BY-NC-ND license:https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh

在遵循署名、非商业使用(以获利为准)以及禁止演绎的前提下可以自由阅读、分享、转发、复制、分发等。

1. 概述

考虑到信息安全问题,这里不会写什么架构设计方案,更不会写什么具体的落地方案,有的只是从理论到实践再从实践回到理论的一些系统工程经验总结。超大规模集群性能调优的目标是为了解决以下两个系统级难题:

1)如何将Ai加速卡千卡分布式训练集群某个模型的加速比调到0.90+以上?

2)如何夯实Ai加速卡整体的分布式训练集群产品的系统级性能质量?

千卡级别的超大规模分布式训练集群性能调试是一个系统级的难题,将理论与实践相结合,从实践中来到实践中去,需要手把手的去调、去敲代码、系统梳理、具体问题具体分析、人技合一,才能有效达成目标。

系统级的性能优化考验的是具体问题具体分析的能力,考验的是根据不同的实际情况的变化进行全局优化的能力。

2. 基本约束条件

1)分布式训练必须以模型能收敛、精度达标、曲线拟合为前提,一切不能收敛、精度不达标、不能曲线集合的性能优化方案都是无效的;

2)加速比计算公式的 speedup = 分布式的单卡性能/单卡性能,这里的分母不是单机的性能,也不是单机内多卡并行计算的单卡性能,做低分母数值从而获得较高的加速比数据属于自欺欺人的行为;

3)理论上加速比也可以是 计算时间/(计算时间 + 非计算时间),因此,加速比调优的本质在于减少或者隐藏非计算时间;

4)这里讲的属于数据并行的分布式训练范畴,非模型并行、流水并行以及混合并行;

5)这里的Ai加速卡指的是某国产化加速卡,在软硬件功能与生态上对比GPU都还有很大差距,短板也更明显,因此更难以调试。

3.性能优化总诀

在软件工程中,不管场景是怎么样的,性能优化的策略本质上都可以抽象成以下几个方案:

  • 少读少写少依赖: 少读,即减少读放大,减少需要读的数据量;少写,即减少写放大,减少需要写的数据量;少读少写的策略可以是提高cache命中率也可以是进行数据压缩,还可以是合适的读写算法与数据结构等,少依赖,高内聚低耦合、资源解耦与隔离,一个组件的IO尽量做到不需要等待另外组件IO完成才能返回;

  • 时空换同异换: 时空换同异换讲的是性能优化的路数,解读开来说即是:时间换空间、空间换时间、同步换异步。例如:采用cache的功能可以减少计算的时间,这是存储空间换时间从而提升性能;采用批处理的方式提升性能,这是减少计算时间;采用同步换异步的方式提升性能也是减少计算时间;减少IO的数据量从而提升性能,这是存储空间换时间;缩短IO路径提升性能,这也是网络空间换时间,采用最新的硬件提升性能,这可以是计算换时间,也可以是存储或网络空间换时间;

  • 硬件顺天性:硬件顺天性讲的是软件设计要遵循硬件的原生特性,XPU不同于GPU、CPU的亲合性、机械盘性能不如固态硬盘、磁盘数据分块需要对齐、内存性能好适合做缓存但是下电就丢数据、网络是不可靠的并且有带宽限制、RDMA网络比IP网络性能好、且是可以双工的,不同的应用场景要依据硬件的不同特性做架构选型以及架构设计等。

对于系统优化来说,不管场景怎么变化,不变的道理其实也还是上面那三项,性能优化也是万变不离其宗的。

4. 几个关键点

关于整体的超大规模分布式训练系统性能优化,需要考虑的主要关键点有以下几项:

  • 工程方法论

  • 极致系统平衡

  • 具体问题具体分析

  • 网络通信优化

  • 数据IO优化

  • 训练框架优化

  • 模型优化

  • 系统优化

下面将围绕这几项展开讲述。

5. 工程方法论之美

5.1 组织到位

千卡性能调优是个系统工程,要干活就首先需要有人,有人就需要组织能到位。这里的组织到位有两层意思:一是需要有人,需要组织给与人力保障以及多团队合作保障;二是合适的人,事是需要人去做的,攻坚的课题用到合适的人才具备达成目标的可能性,用错人半途而废或者数据造假忽悠群众、效果打折的可能性也不是没有。

5.2 架构先行

从系统而非单点的角度分析问题,要解决问题首先是需要能发现问题,在对调优任务进行拆解之前需要对性能调优方案先进行系统分析,挖掘出存在的软硬件问题拿出具体可执行的调优解决方案,并形成架构设计文档。

5.3 分而治之

系统思考分而治之,大问题拆解成小问题,将非常大的不确定性的千卡加速比 0.90+ 这个目标进行拆解,将非确定性的大问题拆解成确定性的小问题,步步迭代进行解决。宏观是不确定的,但微观却可以确定,系统梳理每个要素,拆解为确定的细分任务,先将确定的任务落实到人,再将剩下的不确定任务根据实际情况的变化,逐步进一步分解,逐步迭代。

5.4 小即是大

从主机内单卡到主机内多卡,新增主机内通信单元,从主机内多卡到主机间多卡新增主机间通信单元,这些系统间要素连接关系变化会引起系统整体功能的变化,因此,需要先聚焦主机内单机多卡调优,再聚焦主机间2机性能调优,在这二者达成既定目标后,后续扩展到千卡规模也就是水到渠成之事。

5.5 众策众智

众策众智多方协作,集群性能调优是个系统工程,需要多方合作与协调,其涉及多方组件,千卡性能调优是多方合作的结果,是软硬件联合,软件内部多方合作,跨部门跨团队联调达成的结果。

5.6 躬身入局

躬身入局不达目标不罢休,实践出真知,“黄沙百战穿金甲,不破楼兰终不还”,在认知上确定关键路径后,更重要的是躬身入局实践,一个问题一个问题的攻克,步步为营,步步迭代,一个小目标一个小目标的攻克递进。

6. 系统平衡之美

系统是有灵魂的,如下图《一根羽毛的力量》(图片来源于网络版权归原作者所有),其将平衡用到极致,风、呼吸、声音等微小的外部条件变化都可能造成失败,体现了整体的系统平衡之美。

平衡之美

而分布式训练系统也有自己的灵魂,其可以表达为FPS每秒处理的帧数指标图,一个好的分布式训练系统FPS指标也是很有规律很漂亮的,如下图所示,千卡某模型加速比0.90+达标的训练集群FPS指标可以稳得如同一根直线,完美的诠释了什么是系统工程平衡之美。

平衡之美

而一个加速比指标很差的训练系统FPS指标可能如下图,各种指标上串下跳极其不稳定,缺少一种平衡感。

平衡之美

7. 具体问题具体分析之美

GPU有适合GPU的最佳性能优化方案,XPU有XPU的最佳性能优化方案,而现有的分布式训练方案基本上都是基于GPU硬件体系结构以及CUDA的软件生态方案,不一定适合于各家国产化的AI加速卡的实际情况,因此针对国产化加速卡的性能优化方案也需要具体问题具体分析。

其实对于分布式训练性能优化来说,具体问题具体分析这一步才是最重要的,也是各路性能优化专家的掉坑点。每个AI加速卡都具备矛盾的普遍性也具备自身的矛盾特殊性。要根据自家加速卡的实际情况具体问题具体分析,首先是需要能发现具体的问题,再根据这个具体问题进行具体分析,再根据分析的结果给出最佳适合的性能优化方案,这就跟人的能力强相关,不是看完这篇文章或者网上找的几篇论文就可以完成超大规模训练集群性能优化这个系统级难题的。

各个国产化厂家的硬件存在矛盾特殊性,软件也存在自身的矛盾特殊性,具体问题具体分析就是挖掘这些矛盾特殊性,形成系统性的调研报告,从而给出系统级的性能优化方案。

8.网络通信优化之美

8.1 网络拓扑结构

实践证明,如果网络优化的足够到位,2D-RING ALLReduce拓扑算法就能满足千卡集群某模型的加速比达0.90+的,如下图,主机内一个ring Allreduce,主机间一个ring AllReduce,再主机内一个Broadcast:

2DRING

这种拓扑算法只需要消耗一个RDMA网卡的一个网口以及一个交换机端口,因此,适合在有成本约束的生产环境,除非有更高的加速比要求,不然简单的两层RING结构拓扑算法就能满足绝大多数的生产需求。

而这种网络拓扑优化的关键在于主机内从单卡到多卡,发生了物理连接结构变化,主机间从单机到多机也发生了物理连接结构的变化,要专注于这两种结构变化的优化,使得FPS性能掉的足够少,才有望在千卡这种规模的集群下获得较高的加速比。

8.2 网络存在的问题

网络是分布式训练系统的连接方式,因此分布式训练系统也继承了网络的原生缺点,即:

  • 网络是不可靠的;
  • 网络是会出故障的;
  • 网络是有时延的;
  • 网络是会抖动的;
  • 网络是不安全的;
  • 网络是会丢包的;
  • 网络是有带宽限制的;
  • 网络消息是会乱序的

这些原生缺点的存在会给分布式训练系统带来以下一些问题:

8.2.1 同步通信问题

在Ring拓扑下每个XPU只与相邻XPU通信,而在该拓扑下所有传输都是在离散迭代中同步进行的并且每张XPU都需要进行迭代周期同步,所有传输的速度受到环中相邻XPU之间最慢(或最低带宽)连接的限制,性能瓶颈也非常明显。

8.2.2 落后者问题

落后者 (Straggler)问题,指的是当一个平台上不同的工作单元具有不同的运行性能时,整个系统的性能受限于运行效率最低的工作单元。Straggler可能是确定性的,比如某台机器的计算能力或者网络带宽低于其他机器。也可能是随机性的,比如低性能是因为资源共享,后台操作系统任务,缓存,功耗限制等引起的,解决Straggler问题的一种常用方式是进行异步训练

8.2.3 异质问题

当前我们的国产化软硬件存在一些技术约束,这些约束条件会造成很大的计算异质问题,比如主机内网络非全连接,主机间RDMA全连接并且主机间RDMA有些场景下又是分层交换机互联,这就是网络异质,而目前使用的Ring-Based通信拓扑又是同步的,当整个集群内存在较慢的计算节点时,整个系统的性能受限于这个性能最差的节点。除了网络拓扑,网络本身的缺点也决定了需要对网络进行细致的优化。

9.数据IO优化之美

在分布式训练系统里,数据IO最重要的优化即数据预取以及IO时间隐藏的优化,如下图所示,数据首先从磁盘读取进主机缓存,再从主机缓存读取进加速卡内存HBM,这个过程带宽是受PCIE限制的,如果IO 速率跟不上加速卡的计算消耗数据速率,数据IO就会成为整个训练系统的瓶颈。

数据IO

基于此,需要打通pinned memory ,数据预取以及IO时间隐藏功能。

10.训练框架优化之美

如下图所示,神经网路是分层的,因此训练框架计算出来的梯度也是分层结构,如果不进行融合优化,那么每个梯度层都会触发一次全局通信规约,100个梯度就需要进行100次全局通信100次全局规约,这种行为会极大的拖垮整个分布式训练系统的性能。

神经网络

基于此需要采用 梯度融合的策略进行优化,通过梯度融合计算将多个梯度合成一个,从而减少全局规约的次数能大幅提高分布式训练的训练性能,如下图所示,将N个小梯度Tensor合成两个,能将全局通信的次数减少到2次,从而大幅提升训练性能:

tensorfusion

11. 模型优化之美

这需要具体问题具体分析,根据不同的模型以及实际情况进行优化。除了通信、框架、数据IO等,模型也是影响整体系统性能的一个关键点,数据dataset的效率,训练session 的合并还是分离,采用的是动态训练策略还是静态训练策略,FPS统计的计算方式这些要素也会极大的影响整体的系统性能,因此也需要针对具体情况进行具体分析。

12.系统优化之美

如下图,是一个AI服务器主板,在这个服务器里,加速卡间的通信带宽大于PCIE带宽又大于CPU间的UPI带宽,因此需要启用NUMA优化,使得数据不跨越UPI通信,另外CPU 的AFFINITY也需要进行平衡优化。

数据IO

除了CPU的优化,计算机节点还有一下特性:

  • 计算机节点是会出故障的,主板、CPU、网卡、硬盘、内存、电源等都会出故障,比如老化、失效等;
  • 计算机节点内的操作系统是会突然奔溃不能提供服务的;
  • 计算机节点是会突然掉电的;
  • 计算机节点里的内存下电是不保数据的;
  • 计算机节点的资源是有限的:CPU是有算力上限的、内存是有大小限制的、网卡有吞吐量限制、硬盘有空间大小限制以及速率限制;

这些特性也会影响到训练FPS的平衡,也需要针对性的根据具体情况进行优化。

13. 小结

本文介绍了从实践中来的关于一些超大规模训练集群性能优化的理论上的思考,考虑到信息安全问题,有些地方写的不是很透明,见谅。另外性能优化也是需要具体问题具体分析,根据不同的实际情况而进行优化的,普遍的策略可以学习,但是特殊的情况考验的还是个人以及团队发现问题、分析问题、解决问题的能力。

日拱一卒,功不唐捐,分享是最好的学习,与其跟随不如创新,希望这个知识点对大家有用。另作者能力与认知都有限,”我讲的,可能都是错的“,欢迎大家拍砖留念。

14. 作者简介

常平,中科大硕,某AI芯片公司深度学习高级软件主管、架构师,前EMC资深首席工程师,主要工作背景在深度学习、Ai平台、系统调优、大数据、云计算以及Linux内核领域。

15. 参考资料

[1] https://www.changping.me

[2] NF5468M5 用户手册

16. 版权申明

本文的版权协议为 CC-BY-NC-ND license:https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh

在遵循署名、非商业使用(以获利为准)以及禁止演绎的前提下可以自由阅读、分享、转发、复制、分发等。

1. 前言

哲学是系统化的世界观与方法论,也是分析问题、解决问题的无上心法,当我们面临的问题越复杂时它就越有用,越能发挥出它的无上威力。分析问题、解决问题的无上心法是通过不断的实践和积累经验来炼成的。它需要一个人不断地思考、分析、实践,以及从失败中吸取教训,不断积累经验,最终形成一套完整的分析问题、解决问题的方法。

这里给大家分享一套经过实践证明比较有效的分析问题、解决问题的工作方法,即以世界观、辩证法、实践论、矛盾论与历史观这五大哲学思维来分析问题、解决问题。

另外,社会存在决定社会意识,我写的都是我的社会存在方式所决定的意识形态,是在我个人特殊的立场下的观点与方法,因此我讲的不一定都是对的,也不一定适用于大家的普遍或特殊情况。

2. 世界观

唯物主义世界观认为:世界是物质的,世界是系统的,世界是运动、变化、联系、发展的,世界是对立统一矛盾的,世界是可以认识与改造的,世界是由利益与价值驱动的。

2.1 世界是物质的

2.1.1 一切从客观实际出发

世界是物质的,客观实在性是物质的根本属性,客观存在决定主观意识,主观意识必须符合客观实际。这告诉我们工作中要一切从客观实际出发,使主观符合客观。人的一切认识、意图、设想、目标规划等都是主观,而人的生活环境、生活关系、生产方式、自然物质等都是客观,更进一步可以认为”别人的想法也是客观事实”,比如”上情与下情“,因此可以认为”除我之外皆是客观”,一切从客观实际出发也是从 “除我之外”出发。

2.1.2 解放思想实事求是

一切从客观实际出发也要求我们在工作中 “解放思想,实事求是”。 “实事”即客观存在的事物,“求”即探索、研究、调查,“是”即事物的内部规律、本质。实事求是要求我们事前要解放思想从客观实际出发充分调查研究,找出其中的内部规律与本质,从而避免或减少犯主观错误。

2.1.3 认识并且利用规律

世界是物质的,物质是运动的,运动是有规律的,因此我们工作中也可以认识并且利用规律,比如“如何将酷技术转化成好产品”,这就是有规律可循的,找出这个规律就可以指导任何的将技术转化成产品的各种产品化场景。

2.2 世界是系统的

2.2.1 全面观

世界是系统的,系统具有整体性,因此我们要整体全面地认识问题、分析问题、解决问题。看一个茶杯,坐在不同位置的人看到的都有可能是不同的图案,盲人摸象也是因为只看到局部而没看到全局做造成,因此世界是系统的首先就要求我们办事要具备全局观,从而减少犯错误。

2.2.2 要素联系与目的

系统观认为系统是由相互联系、相互作用的要素组成的,这些要素的组合达成了统一的目标、目的或功能。在系统里,要素的联系以及系统的整体目标、目的、功能,会比要素更为重要,属于系统质的部分,而要素属于系统 量的部分,量的变化在没有引起质的变化之前是不大会影响到整体系统的功能或目标的,而 质的部分的变化会导致系统功能发生剧烈变化。

比如一个企业也可以看做一个系统,企业内部的员工可以看成是要素,要素未达到质变的有限变化前并不会改变这个企业系统的基本功能与目标,比如“企业裁员或员工跳槽”。而企业功能的改变,比如从生产水产变成生产芯片,其功能就发生质的变化,再比如汇报关系即联系关系发生变化也会大面积的引起企业基本功能或目标的变化。

2.2.3 平衡

系统 = 要素 x 联系 + 目的/功能。系统论也告诉我们要让系统跑的又稳又快那么就要求系统内的各要素之间的联系与资源竞用达到了最佳的平衡态,即熵的平衡态。热力学第一定律告诉我们 一个系统一定会从有序走向无序,从整齐走向混乱,要改变这个状态即需要从外部做功,给系统输入新的能量,比如企业的管理也是为了减少内部的熵增,从而延长企业系统的生命周期。因此,我们在工作中要平衡/隔离各个团队要素,令组织资源竞用达到平衡,从而减少组织冲突,延缓熵增。

2.3 世界是运动、变化、联系、发展的

2.3.1 一切以时间、空间、条件为转移

世界是运动、变化、联系、发展的,这告诉我们办事要 “一切以时间、空间、条件为转移”,时间:过去、现在、未来,空间:大势、环境、境况、民意、民情,条件:客观条件与主观条件。当事物的时间、空间、条件发生变化时,我们工作中也要根据具体情况、具体条件以及时间、空间调整办事的策略。

2.4 世界是对立统一矛盾的

2.4.1 一分为二

世界是对立统一矛盾的,回答了事物发展过程的原因是什么的问题,揭示了发展的根源是事物内部的矛盾运动。矛盾就是对立统一,这告诉我们要坚持 一分为二、全面地看待问题。这一部分对应着 伟人三大绝学的《矛盾论》,后续章节详解。

2.5 世界是可以认识与改造的

2.5.1 学以致用

世界是可以认识与改造的,告诉我们认识世界是为了改造世界,人的精力与时间都是有限的,学习要能致用、要能指导工作实践、要能对工作对生活对人生有价值,不然学习也是一种玩物丧志。这一部分对应着伟人三大绝学的《实践论》,后续章节详解。

2.6 世界是由利益与价值驱动的

2.6.1 利益、价值与面子

世界是由利益与价值驱动的,利益与价值也是这个世界基本的运作规律,当然有些时候除了利益与价值还有国人的面子问题。这一部分对应着伟人三大绝学的《历史观》,后续章节详解。

3. 唯物辩证法

唯物辩证法由一个主义、两种观点、三个定律、四项思维以及五大范畴所组成,即:

  • 一个主义:世界是物质的

  • 两种观点:世界是联系与发展的

  • 三个定律:对立统一,质量互变,否定之否定

  • 四项思维:归纳与演绎,分析与综合,抽象与具体,逻辑与历史

  • 五大范畴:原因与结果,内容与形式,本质与现象,必然与偶然,可能与现实

世界是物质的定义了唯物辩证法的 立场、观点与方法,辩证法是唯物的辩证法。联系与发展,告诉我们要以系统的观点看问题,以变化的观点看待问题。三大定律里对立统一规律是本质,质量互变规律是质与量的对立与统一,否定之否定规律是肯定与否定的对立与统一。而四项思维是四项对立与统一的关系,五大范畴是质与量的关系,因此唯物辩证法也可以认为是客观世界的联系与发展以及对立与统一的根本方法。

这一章节也被分散到 世界观,系统观,实践论、矛盾论、历史观里做了讲述,因此这里不再重复。

4. 实践论

“纸上得来终觉浅,绝知此事要躬行“,实践是认识的来源、标准、动力与目的,从感性认识上升为理性认识是实践出真知,实践的观点是认识论的基本观点,认识与实践 的关系等同于 知与行的关系,如同“知行合一”的观点一样实践的观点也有三大层次:

  • 第一层是认识指导实践,比如以已往的经验、知识指导工作实践;

  • 第二层次是:认识与实践是循环往复以至无穷的,实践认识再认识实践,事前调查研究,事后复盘总结;

  • 第三层次是:坚持以上两种层次,做事有韧性;

实践论也认为认识世界是为了改造世界,认识是人对客观事物的认识,只有解放思想才能实事求是,要根据客观事实,引出思想路线,提出方针政策才能把事情能做好。实践的观点也要求我们在工作中要“去粗存精,去伪存真,由此及彼,由表及里”, 才能将感性认识升级成理性认识,从而更好的指导实践。

5. 矛盾论

矛盾即对立统一,唯物辩证法里的三大规律里,否定与肯定是对立与统一,质与量也是对立与统一,因此对立统一规律是最为基本的规律。对立统一规律告诉我们要一分为二的看待问题,但是这个一分为二与系统论的一分为三,一分为多是有本质差别的,前者是质,后者是量。

5.1 对立统一

矛盾就是对立统一,更好理解一点可以将矛盾理解成 国人熟知的 “阴阳”, 阴阳是循环运动在一定的条件下变化发展的,矛盾的对立统一规律告诉我们做事要一分为二,要辩证的看待问题,不要非黑即白。

5.2 普遍与特殊

矛盾的普遍性告诉我们事物是普遍矛盾存在的,问题也是普遍的,不同的人,不同的场景,不同的时空,矛盾都是普遍的。工作中觉得一这份工作不顺利,就想通过换工作来解决,但是矛盾的普遍性会告诉我们换了工作这个问题也许是解决了,但是新的问题一定会出现。矛盾的普遍性也决定了工作中员工有员工的难处,老板也有老板的难处,而且“钱多事少离家近,位高权重责任轻。睡觉睡到自然醒,数钱数到手抽筋” 这样的情况是基本上不可能会存在的。

矛盾的特殊性告诉我们做事具体问题要具体分析。以普遍打特殊或者以特殊打普遍,都必然会出问题。比如公司内政策是自带普遍属性的,但是不同的部门,不同的个人情况又是有特殊的,这就要求我们工作中要注意具体问题具体分析,不搞一刀切。

5.3 不平衡

矛盾的不平衡要求我们做事既要坚持重点论,又要坚持两点论,要用“弹钢琴”的手法来做事,有重按键,有轻按键,还要每个键都兼顾到,这样弹出来的才是美妙的音律。

坚持两点论和重点论相统一, 要求我们做事既要抓住主要矛盾 同时也要兼顾次要矛盾,在有限的资源下,要集中资源打歼灭战,打关键的卡脖子重点战,如果分散资源普遍开花只会得不偿失,或者达不到想要的效果。

矛盾的不平衡,也告诉我们工作中要抓重点带全局,稳定全局、重点突破、以点及面、梯度推进、波浪式前进。

5.4 质量互变

量变是重视量的积累,反对急于求成。质变是要果断抓住时机,实现事物的飞跃,也要坚持适度原则,不能随意造成质变。

质量互变,关键是度的达成,水在100°时会变成气态,在0°时会变成固态,条件达成才会触发质与量的互变。因此要想质与量发生互变,就要积累条件使之发生变化。

5.5 否定之否定

否定之否定,维持自身为“肯定”,灭亡自身为“否定”。肯定与否定是对立与统一的,事物通过否定自我达成肯定自我,通过批评自我达成提升自我,因此我们工作过程中也要经常开展批评与自我批评,从而提升自我的工作能力。

新事物是从旧事物中通过否定自我来达成的,因此这也给我们工作中的创新提供了指导思想:需要从旧事物中进行否定从而获得新事物的肯定。

6. 历史观

6.1 群众观

群众观是历史观的基本观点,走群众路线从群众中来才能形成正确的认识,到群众中去,才能将正确的认识转化成群众的行动。从群众中来,到群众中去,领导与群众相结合是集体组织工作的根本工作路线与方法。

群众观,告诉我们做事的时候,要走群众路线,关注群众观点,关注上情,也关注下情,通过民主集中制的原则,从群众中来到群众中去。事前调查研究、事中交换意见比较调整、事后复盘总结。

6.2 利益观

物质利益是这个世界的最基本的驱动力之一,国家、集体、个人都有自己的利益述求。利益是引起一切社会冲突、组织冲突、个人冲突的最终根源也是社会历史发展的内在动因,人们通过追求利益促使社会历史不断前进。

如果不讲利益只讲道德与奉献,是犯了维心主义的主观错误,不符合客观实际、也不实事求是,但如果只讲利益而不讲道德与奉献,那是唯利是图,也不符合人的 真 善 美要求。

利益分析法也是基本的工作方法之一,在推动一项组织工作时,心里要清楚干系人的利益与立场,谁会支持、谁可能会反对、谁可能无所谓、谁可能会需要更多信息输入都要心里有数,支持的原因是什么,反对的原因是什么,无所谓的原因是什么,事前调查研究充分,事中交换意见比较调整,才能增加把事情做成的成功概率。

6.3 价值观

价值分为两大类,事物的价值与人的价值。常见的价值可从以下五个维度划分:命、利、真、善、美。即保命的,满足物质利益的,求知求真的,道德向善与超我成圣的。

价值是客观的,事物的价值在工作中可以理解为产品的价值,产品要能给用户带来价值,能满足用户的需要,才具备价值。人的价值体现在工作中,本质上是价值的交换,企业给你发工资(价格),个人贡献你的价值,当价格匹配价值时就符合价值规律,当不匹配时时间一长就总有一方会感到不满。

价值也是主观的,会因人而已的,不同的时间、条件、环境下对于不同的人来说价值也会不尽相同,也会出现不断的变化。价值因人而异是十分常见的现象,价值评价标准是由价值制定阶层来决定的,带有人的好与恶,以及天然利于自我阶层的属性,而被评价阶层往往只能承受这个评价标准。

价值分析法也是基本的工作法之一。因此,工作中,要令价值评价尽量达到客观,就需要在评价前多做调查,多做研究,多交换意见,不以人的好恶为标准,而应该以客观事实为标准。

6.4 社会存在与社会意识

一个组织内的高层人员有时会觉得执行人员缺乏全局观,而执行层又觉得高层们”肉食者鄙”。这是由其社会存在方式的差异所决定的,在生产过程中形成的位置的不同获得的信息也不同,自然看到的情况也不同。

社会存在决定社会意识,但社会意识也能反作用于社会存在。高层可以通过躬身实践获得更多的细节特殊性,而执行层也能通过学习以及请教获得更多的信息以及提升自己的全局观能力。

但,虽然社会意识也能反作用于社会存在,要改变自己的社会意识(认知),最主要的还是要改变自己的社会存在方式,毕竟,认识来自于实践。

7. 小结

基于以上的五大哲学心法:世界观、辩证法、实践论、矛盾论、历史观。可知要做成事、做好事,首先要解放思想 、实事求是 、一切从客观实际出发、使主观符合客观,要全面 、本质、联系 、发展 、矛盾地看待问题与分析问题,工作上要走群众路线,抓重点带一般,抓普遍带特殊,抓整体带局部,看利益也看价值,具体问题具体分析,事前调查研究、事中交换意见比较调整、事后复盘总结,实践认识认识再实践如此循环往复以至无穷。

8. 作者简介

常平,中科大硕,某AI芯片公司深度学习高级软件主管、架构师,前EMC资深首席工程师,主要工作背景在深度学习、Ai平台、系统调优、大数据、云计算以及Linux内核领域。邮箱:wu@changping.me

9. 参考资料

[1] 《新大众哲学》

[2] 《哲学思维方式与领导工作方法》

[3] 《遨游之舟》公众号

[4] 《毛选》

10. 版权申明

本文的版权协议为 CC-BY-NC-ND license:https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh

在遵循署名、非商业使用(以获利为准)以及禁止演绎的前提下可以自由阅读、分享、转发、复制、分发等。

1. 概述

分布式训练服务框架与集合通信库的组合构成了分布式训练的整体服务软件栈,在第3篇、第4篇文章里已经剖析完集合通信的相关内容,而本文会以Horovod为例介绍数据并行下分布式训练服务框架的基本原理以及进行架构解析。当前,在分布式训练里分布式训练服务框架需要解决以下几个核心问题 :

  • 计算与通信同步耦合问题:如果反向传播一产生一份梯度,就马上对其调用全局AllReduce,计算与通信同步耦合,容易造成死锁同时性能也会很不如意;
  • 计算时间与通信时间串行问题:神经网络是分层的,梯度计算的过程是数据加载,然后前向传播算出损失值,再反向传播算出梯度,而反向计算时梯度是从输出层往输入层方向一层一层产生的,在有些模型里,如果需要等所有的梯度都计算完毕才能触发全局AllReduce,那么对性能的影响也会很大;
  • 梯度生成的落后者问题:集群内每个计算节点的同一份梯度的产生不一定都是同一时刻的,如果梯度没有全部生成就发起对这个梯度的全局规约,否则容易造成训练出来的模型精度不达标或者不收敛的问题;
  • 梯度融合问题:如果每一份梯度都触发一次全局AllReduce,在梯度Tensor较多的神经网络训练里,整体的训练系统性能会变得极低;
  • 易用性问题:从TensorFlow,PyTorch迁移过来需要改的代码需要极少,从单卡训练迁移到多卡训练需要改动的代码也需要极少;
  • 可移植问题:支持多种多样的深度学习训练框架,比如 TensorFlow、PyTorch、MxNet等,也能支持多种多样的通信库,比如openMPI、NCCL、Gloo、CCL、RCCL等;
  • 可靠性问题:在集群训练的过程中网络时不可靠的、计算卡是会出故障的、服务器是会出故障的、系统软件也是会出Bug的,这些因素造成了分布式训练过程中还存在可靠性问题,如何解决这个问题也是一个难题。

软件是由人实现的,解析一个软件系统最难的地方在于从庞杂的代码里倒推出背后实现它的人的设计意图,为了更好的理解Horovod,本文会基于以上这几个分布式训练的核心问题,以Horovod为例介绍分布式训练服务框架的基本原理以及进行架构解析。

2. 基础知识

2.1 单卡训练

神经网络的训练,本质上就是Y=F(x)的迭代,通过反复输入X、输出Y,使得神经网络的参数变化与输入输出间的复杂关系拟合。在神经网络训练的过程中,通过输入数据利用梯度下降的方法进行迭代从而优化神经网络参数,并最终输出神经网络模型。而神经网络可以看作一种运算模型,其由大量的神经元(节点)相互联接构成,其由输入层、隐藏层以及输出层组合而成(如下图左侧所示)。神经元(neuron)是神经网络的基本计算单元,也被称作节点(node),它可以接受来自其他神经元或外部数据的输入,然后计算出一个输出(如下图右上角所示)。

单卡训练

如上图右下角所示,在单卡训练迭代中,基于并行梯度下降法,会有以下操作:

第一步,读取部分数据,并且将数据加载进训练卡的存储空间;

第二步,对模型进行前向传播计算,从输入层往输出层一层一层的进行计算,得到损失差LOSS;

第三步,对模型进行反向传播计算,从输出层往输入层一层一层的进行计算,得到梯度值,注意这一步会把每一层都计算出一个梯度张量(Gradient Tensor)出来;

第四步,将新的到的梯度与部分数据 作为新的输入,重新开始以上步骤的迭代。

在这一步里有一个很重要的与性能优化相关的信息是反向传播是每一层输出一个梯度张量,以及反向传播是从输出层往输入层一层一层的进行计算的,这一点信息可以用通信隐藏性能优化与梯度融合优化。

2.2 多卡训练

以数据并行随机梯度下降法( SGD )为例,多卡神经网络的训练过程如下图,与单卡训练相比,多卡训练多了梯度全局规约的过程:

多卡训练

第一步,通过Broadcast操作将第一个节点参数同步到集群内的所有的训练卡上,保证每个计算节点的初始参数是一致的,同时训练脚本在多个计算节点上运行,每个计算节点包含了整体的模型参数;

第二步,将数据样本切片分发到整个集群内的个计算节点(训练卡)上并且通过数据流水技术将数据样本加载进训练卡的高速内存空间内,作为输入X;

第三步,每个训练卡在其数据样本上运行前向传播,计算出损失差LOSSi;

第四步,对计算出的LOSSi进行反向传播,得到梯度GRADi,这一步也需要注意得是每一层都会计算出一个梯度,同时梯度是以输出的Tensor来表示的;

第五步,所有的训练卡计算出来的部分梯度,在主机内及主机之间通过集合通信进行全局归约(AllReduce)得到全局梯度;

第六步,最后再将这个全局梯度作为参数进行更新,再进行以上2-5步骤的迭代从而获得新的梯度。

以上2-6步骤就是多卡并行梯度下降的基本思想,即多个计算节点通过分片的数据样本进行梯度计算,得到分区梯度后,再通过全局梯度规约以及将这个聚合好的梯度作为新的参数进行更新,从而实现并行梯度下降。

3. 几个核心问题

在本章节里会解读本文概述里提到的分布式服务框架需要解决的几个与性能、易用性等相关的几个核心问题,并且以Horovod为例讲述Horovod是如何解决这个几个难题的。

3.1 计算与通信解耦

在神经网络的训练过程中,每一神经网络层都会计算出一个梯度,同时梯度是以输出Tensor来表示的,如果反向传播一计算出一个梯度就马上调用通信去做梯度规约,将计算与通信同步耦合,那么整体的性能的表现就会很差。比如一个ResNet-50 v3的梯度张量个数是153个,如果一计算出一个梯度就马上进行通信,假设计算梯度花了1ms,通信这个梯度花了 500ms,那么这个过程就是 501ms,总体上就需要501x153 = 76653ms,即近76.6s才能完成一次梯度迭代。而将计算与通信解耦,计算的归计算,通信的归通信,通过性能优化策略减少通信的次数,既能提升整体训练性能也能避免某些死锁问题,比如计算梯度grad i的时候花了很长时间,而通信线程一直在等待这个梯度,表现出来就是死锁现象。

Horovod采用计算与通信分离的设计思想,解耦了计算过程与通信过程,从而提升了整体训练的性能与可靠性。如下图的Horovod逻辑架构图所示,从图中可以看出Horovod解耦了计算与通信,其将框架层计算出来的梯度request信息push 到一个消息队列message_queue里,同时将梯度信息push到一个Tensor_table里,再通过控制层在后台起一个loop线程,周期性的从消息队列里读取梯度消息,在控制层集群的节点之间协商达成一致后,再进行消息分发触发训练行为。

Horovod逻辑架构

如上图可看出,Horovod从下到上分为7层:物理层、链路层、数据传输层、控制层、消息层、框架层以及用户层。框架层,控制层以及数据传输层体现了Horovod的核心设计理念,即:框架层,用户可以自定义Op,以插件的形式hack进框架;在控制层,worker节点与master节点之间协商达成触发训练行为的约定;在数据传输层,服务器内以及服务器之间采用集合通信库传输数据。

本质上Horovod的整体设计理念之一遵循的是生产者消费者模式,如下图所示:

生产者-消费者

在Horovod里每个计算节点都会有有两个核心线程:Execution thread 和 Background thread :

  • 生产者Execution Thread 是用来做梯度计算的,在TensorFlow、PyTorch之类的之类的训练框架计算出梯度Tensor后,将Tensor 信息push进tenor_table队列,同时将Tensor的request信息push进message_queue队列;
  • 消费者Background thread 是做集合通讯以及全局Allreduce的,后台线程会每隔一段时间轮询消息队列,拿到一批Tensor信息之后,会进行相应的操作。

3.2 通信隐藏

神经网络是分层的,在训练的过程中,先是数据加载,然后前向传播算出LOSS,再反向传播算出梯度,而反向计算时梯度是从输出层往输入层方向一层一层产生的,如果需要等所有的梯度都计算完毕才能触发全局AllReduce,对性能不是很友好。如下图所示,计算时间与通信时间是串行的,如果能将全局梯度规约的通信时间与计算时间想办法并行起来,将通信时间隐藏在计算时间之内,那么就能节约梯度的训练时间从而提升分布式训练系统整体的训练性能。

通信隐藏

如下图所示,将计算出来的梯度进行分桶触发异步Allreduce,一边反向传播计算梯度,一边做部分梯度的全局规约通信,从而达到将通信时间隐藏在计算时间内的效果。而Horovod为达成这一效果,Background thread 会每隔一段时间轮询梯度消息队列里的梯度信息,获取了可以过全局规约的梯度后,就进行全局规约操作,而这个时间其他的梯度还在计算过程中,通过调整轮询的时间间隔从而达到调整梯度分桶的效果。

通信隐藏

3.3 梯度协商

神经网络的每一层对应一个梯度Tensor,在分布式训练集群里每张训练卡对同一份梯度计算产生的时间是有差异的,当集群内每个计算节点的同一神经网络层的同一梯度都产生时,才能发起对这个梯度的全局AllReduce规约,否则容易造成丢梯度,训练出来模型精度不达标或者模型不收敛。比如在一个128卡的训练集群里,同一份梯度是对应同一个神经网络模型里的同一层神经网络的,只有每张训练卡上都计算出了同一层神经网络的梯度 才能对这一层神经网络的梯度进行全局规约,如下图所示:

梯度分层

Horovod设计了一种梯度状态协商机制,它将 计算节点Rank0 作为coordinator(master),其余的rank1-N节点进程为worker,由coordinator来协商确定同一份梯度是否在每个计算节点上都已经计算出来,只有在每个计算节点上都计算出来的同一梯度才可以进行全局规约操作。在Horovod里每个计算节点上都有一个message_queue以及tensor_table,而在coordinator节点上除此之外,还有一个message_table用于保存可以进行全局Allreduce的梯度请求次数信息。Horovod 控制面的ComputeResponseList 函数里实现了这一梯度的协商过程,在从message_queue获取了本节点生成的梯度信息后,coordinator会与其他节点协商这个梯度是否都计算出来,这一过程是阻塞进行的,这个协商过程如下图:

梯度状态协商

一个梯度是否能满足全局规约AllReduce的协商过程如下:

首先,集群内的每个计算节点进程都会往coordinator Rank0发送一个 tensor的请求request,表示说本节点这一层神经网络的梯度已经生成,比如tensor1,每个rank都会往rank0 发送一个本梯度tensor1已经计算出来的请求信息;

第二步,coordinator接收到节点的梯度协商请求后(包括本节点),会把收到的tensor请求次数进行累加,并将这个信息记录在message_table里,当这个梯度的请求信息达到集群内节点的个数时,比如在N个节点的集群,一个神经网络层的梯度tensor的通信请求出现了N次,那就表示在本集群里所有的计算节点都已经发出了对该梯度tensor的通信request,这就表明这个梯度tensor是符合全局规约要求的,就能进行集合通信全局规约,不符合要求的梯度tensor将继续留在message_table中,直到条件符合为止;

第三步,再接着coordinator会将满足全局allreduce规约条件的梯度Tensor通过response返回给其他节点,告诉其他节点这个梯度可以启动全局规约AllReduce。

经过这几步的协商达成梯度全局状态一致的目的,从而避免梯度丢失造成的模型精度不达标、不收敛或者进程死锁问题。

3.4 梯度融合

神经网络的每一层都能对应一个梯度,假设每生成一个梯度就进行一次全局规约时,100个梯度就需要进行100次全局通信100次全局规约,而通信对训练的性能有巨大的影响,这种情况表现出来的效果就是分布式训练集群的整体性能极差。通过梯度融合计算将多个梯度合成一个,从而减少全局规约的次数能大幅提高分布式训练的训练性能,如下图所示,将N个小梯度Tensor合成两个,能将全局通信的次数减少到2次,从而大幅提升训练性能,在Horovod里这个功能对TensorFusion特性。但这个特性也会与3.2通信隐藏特性相冲突,需要根据具体情况进行合理的调试优化。

tensorfusion

3.5 易用性

从TensorFlow,PyTorch等框架迁移到Horovod需要改的的代码极少,horovod接入方式比较简单,与原生训练框架对比,主要的区别在于:

1
2
3
4
5
6
7
8
9
10
11
12
13
1,初始化 Horovod,包括机器资源的分配:
horovod.init()

2,向每个进程分配XPU资源, 典型的设置是 1 个 XPU 一个进程,即设置 local rank:

config.gpu_options.visible_device_list = str(hvd.local_rank())

3,对原优化器进行包装,分布式优化器将梯度计算委托给原始优化器,使用allreduce或allgather对梯度求平均,然后应用这些平均梯度:

opt=hvd.DistributedOptimizer(opt)

4, 将初始化参数从rank 0广播给其他进程(rank表示进程序号),实现参数的初始化,确保所有节点的初始化参数保持一致:
hvd.BroadcastGlobalVariablesHook(0):

3.6 可移植

可移植问题,Horovod通过 OP和OpKernels的插件化机制支持多种多样的深度学习训练框架,比如 TensorFlow、PyTorch、MxNet等。基于的opKernels的可定制化机制,Horovod自定义了Op然后hack了数据链路层的通信协议,从而达到在多个深度学习框架之间可移植。

3.7 可靠性问题

在集群训练的过程中网络时不可靠的、计算卡是会出故障的、服务器是会出故障的的,这些因素造成了分布式训练过程中需要考虑训练集群的可靠性,Horovod结合集合通信库Gloo对外提供了弹性训练的特性,但可靠性不只是弹性训练就能完全解决的,它还有更多的系统级的问题需要解决,因此可靠性问题留着一个后续研究问题,不在本文阐述。

4. 优点缺点、改进点

选择一个框架也是辩证的,在获得它优点的同时也得接受它的缺点,Horovod的优点、缺点以及改进点描述如下:

4.1 Horovod优点

  • 简单易用、可移植,并且支持弹性训练提升了可靠性;
  • 不依赖于某个框架,其通过MPI机制独立建立了一套分布式训练服务系统;
  • 将计算与通信分离,完成了allreduce、allgather等集合通信工作,实现了规模可扩展;
  • 巧妙的通过间隔轮询的机制支持通信时间隐藏,并且完成了梯度协商从而保证训练出来的模型是可收敛、精度达标的;
  • 支持梯度融合,支持将小的tensor合并成一个大的tensor再进行通信传递,从而减小通信操作的额外开销;
  • 自带压缩算法,可以减少集合通信的数据量;

4.2 Horovod的缺点

  • 与GPU绑定,对新的训练加速设备的支持不够友好,缺乏设备插件化的机制,要添加一个新的训练加速设备比较困难;
  • 所有的代码都与CUDA绑定,所有的性能优化机制都是针对GPU的,对新的DSA架构的芯片基本忽视;
  • 弹性训练特性比较复杂,很难在生产上使用起来;
  • 的Message_queue,Tensor_table缺乏容错机制,如果丢失数据容易造成丢tensor,从而影响整体模型的收敛与精度;

4.3 Horovod的改进点

  • 简单易用的插件化支持新的训练芯片;
  • 即支持SIMT架构芯片的性能优化,也支持DSA架构的芯片性能优化;
  • 支持消息队列、张量表的容错,支持Rank 0 容错机制;

5. 思考题

  • 问题1,将通信时间隐藏在计算时间内能有助于提升训练系统的整体性能,但这一特性是针对SIMT芯片的架构的进行性能优化的,如果DSA芯片不能支持这一特性,那应该如何优化Horovod从而大幅提升整体的训练性能?(可以确定这一定是能做到的)
  • 问题2,梯度协商的过程中,每个梯度都需要协商一次,在梯度较多,网络规模较大的集群里,这一特性也会影响性能,如何进行优化才能有效提升Horovod性能?
  • 问题3,不同的模型对梯度融合有不同的要求,那么梯度融合需要融合到什么程度才能有效提升性能?

可以说明的是,这三个问题解决后还能继续提升Horovod在DSA架构芯片上的整体的分布式训练系统级性能。

6. 小结

本文介绍了分布式训练的基础知识以及剖析了分布式训练服务框架所面临的几个核心问题,以Horovod为例从计算与通信解耦、通信隐藏、梯度协商、梯度融合、易用性以及可移植这几个角度倒推了分布式训练服务框架背后的设计意图,从而帮助大家能更好的理解分布式训练服务框架。

日拱一卒,功不唐捐,分享是最好的学习,与其跟随不如创新,希望这个知识点对大家有用。另作者能力与认知都有限,”我讲的,可能都是错的“,欢迎大家拍砖留念。

7. 作者简介

常平,中科大硕,某AI芯片公司深度学习高级软件主管、架构师,前EMC资深首席工程师,主要工作背景在深度学习、Ai平台、系统调优、大数据、云计算以及Linux内核领域。

8. 参考资料

[1] https://www.changping.me
[2] https://horovod.ai
[3] https://www.cnblogs.com/rossiXYZ/p/14910959.html
[4] https://zhuanlan.zhihu.com/p/374575049

9. 版权申明

本文的版权协议为 CC-BY-NC-ND license:https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh

在遵循署名、非商业使用(以获利为准)以及禁止演绎的前提下可以自由阅读、分享、转发、复制、分发等。

1. 概述

在深度学习的分布式训练里,Ring AllReduce拓扑算法奠定了数据并行训练的集合通信基础,但集合通信拓扑不只是仅有Ring Allreduce,经典的集合通信拓扑算法还有2D-Ring/Hierarchical Ring AllReduce,halving and doubling AllReduce,Butterfly AllReduce,2D-Torus AllReduce,2D-Mesh AllReduce,double binary tree等。拓扑算法很多,但也不是所有的拓扑算法都能满足实际的生产需求的,这需要具体问题具体分析、具体场景具体设计。

集合通信的难点在于需要在固定的网络互联结构的约束下进行高效的通信,集合通信拓扑算法与物理网络互联结构强相关,为了发挥网络通信的效率,也不是说就能随意发挥通信拓扑算法,更多的是在效率与成本、带宽与时延、客户要求与质量、创新与产品化等之间进行合理取舍。

充分发挥训练加速卡与网络的效率是通信拓扑算法的初衷,但除了设计高效的集合通信拓扑算法外,分布式训练中需要解决的通信难题还有:网络是异构的,网络带宽是有限的,主机内PCIE SWITCH是有亲和性的,网络是会出故障的,节点是有落后者效应的,设备成本是需要考虑的,数据中心是有部署约束的,用户是有多租户要求的等,这些属于产品化的范畴不在本文阐述。

2. 网络互联结构

分布式训练的集合通信拓扑算法与物理的网络互联结构强相关,而网络互联结构又多种多样,因此,本文需要先对网络互联结构进行约束,依据生产中常用的、既定的互联结构设计集合通信算法,网络互联结构描述如下:

2.1 服务内网络互联结构

以一台集成了8张训练加速卡的服务器为例,如下图:

服务器内互联结构

图片来源于《volta-architecture-whitepaper》,版权归原作者所有

这台服务器内的网络互联情况如下:

1)在这台服务器内,8张训练加速卡通过私有协议连接组成多个主机内的物理ring环,且可双工;

2)服务期内网络带宽 NVLINK>PCIE switch > QPI;

3)加速卡1、2、3、4之间两两全互联,加速卡5,、6、7、8之间两两全互联,2、5、3、8之间非全互联;

4)加速卡1、4与网卡NIC1 挂在同一个PCIE Switch上,具有亲和性,加速卡2、3与网卡NIC2挂在同一个PCIE Switch上,具有亲和性,而PCIE Switch之间也互联,因此 加速卡 1、2、3、4 与网卡NIC 1、NIC2具备亲和性,它们无需通过CPU的QPI线进行通信;

5)加速卡5、8与网卡NIC3 挂在同一个PCIE Switch上,具有亲和性,加速卡6、7与网卡NIC4挂在同一个PCIE Switch上,具有亲和性,而PCIE Switch之间也互联的,因此 加速卡 5、6、7、8 与网卡NIC 3、NIC4具备亲和性,它们也无需通过CPU的QPI线进行通信;

6)网卡可根据需要 选择 1张、2张、4张或8张,最多可以采用8张RDMA物理网卡;

2.2 服务器间网络互联结构

以一个训练加速卡集群为例,如下图是一个常用的CLOS互联架构方案:

整体网络拓扑结构

在这个集群内,其网络互联情况如下:

1)集群内每台服务器自带高速RDMA网卡,通过RDMA 交换机在主机间两两全互联;

2)交换机组成CLOS架构,分为Spine与Leaf交换机,当然也可以是更为高端的Spine、Leaf合一的高端交换机;

3)RDMA网卡与Leaf交换机互联,每台服务器的RDMA网卡数量根据成本与性能考虑,可以是1张、2张+每卡虚拟化4卡、4张+每卡虚拟化2卡或8张;

2.3 高速网卡及其虚拟化使用

RDMA网卡是双工的且可虚拟化,在这里每台服务器可根据成本、性能的考虑选用1张、2张、4张或8张,且在服务器内左右对称,如下图:

网卡配置

从成本与效率的角度考虑,每台服务器内的网卡可以是以下配置:

  • 1张物理RDMA网卡,不进行虚拟化,直接用双工通道,适合选用2D/Hierarchical Ring拓扑算法;
  • 2张物理RDMA网卡,可以每张虚拟化出4个虚拟网卡,2X4共8卡,适合选用2D-MESH、2D-Torus拓扑算法;
  • 4张物理RDMA网卡,可每张虚拟化出2个虚拟网卡,4X2共8卡,适合选用2D-MESH、2D-Torus拓扑算法;
  • 8张物理RDMA网卡,不需要虚拟化,直接采用双工通道,适合选用2D-MESH、2D-Torus拓扑算法;

在实际的分布式训练生产集群中,集合通信算法也可以结合RDMA网卡端口(包括虚拟化的)的具体个数进行设计,而拓扑算法的选择也是需要根据成本与效率的进行合理取舍的。

2.4 网络结构抽象

网络根据连接情况可分为ring结构、mesh结构、 torus 结构以及tree结构,基于以上的服务器内网络互联结构、服务器间网络互联结构以及网卡的具体情况,可以抽象出一个网络结构,即二维环面网络:Torus 网络,而Torus网络横向与纵向都可以看成ring结构,因此相应的拓扑算法基本上就是Ring-Based 集合通信拓扑算法。如下图:

Torus网络结构

TORUS网络是常见的大规模并行计算机的互连网络,在上图这个Torus网络里:

1)横向:主机内8卡通过私有连接协议,比如CXL/CCIX/NVLINK等组成一个或多个ring,如上图的黄色连接线,横向8卡组成二维Torus的横向维度;

2)纵向:主机间通过RDMA(RoCE/IB)网卡、交换机互联组成1到8个ring,如上图的红色连接线,纵向采用RDMA网卡组成二维Torus的纵向维度;

3)根据物理网卡数量、网卡虚拟化以及PCIe Switch亲和性的实际情况:

  • 每台服务器1张网卡可组成主机间一个ring,网卡与XPU0 挂载同一个PCIE switch上,依据最佳实践原则(比如性能、成本、客户要求等),适合选用2D/Hierarchical Ring拓扑算法;
  • 两张网卡可组成主机间两个ring或者经过虚拟化组成8个ring,根据PCIE SWITCH亲和性原则,一张网卡与XPU0挂在同一个pcie switch,另一张网卡与XPU4挂在同一个pcie switch,依据最佳实践原则(比如性能、成本、客户要求等),适合选用2D-MESH、2D-Torus拓扑算法;
  • 4张网卡、8张网卡以此类推,也是根据PCIE SWITCH亲和性原则进行连接,主机间RDMA物理网卡不够就虚拟化网口来凑,并且要服务器内的RDMA出口端口数左右平衡,依据最佳实践原则(比如性能、成本、客户要求等),也是适合选用2D-MESH、2D-Torus拓扑算法,这样才能发挥多张网卡以及XPU的算力优势。

4)更复杂的Torus网络组合关系还可以如下图,从横向只有 主机内的8卡纵向只有主机间的RDMA互联,扩展到 横向与纵向 主机内互联与主机间互联混合,但本文仅限于在横向8卡的二维Torus网络下进行拓扑算法选择与设计,因此不展开讲述。

Torus网络结构

3. 常用的通信拓扑算法

Torus 网络结构可以解读本文中的物理网络互联结构的一切,而Torus网络的横向与纵向都可以看成ring结构,因此,相应的集合通信拓扑算法都可以看成是Ring-Based 集合通信拓扑算法。

3.1 Ring AllReduce

在分布式训练中,Ring 是最基础的互联结构,在本文中Ring AllReduce的应用场景是在服务器内将8张加速卡组环通信进行分布式训练。每个XPU都是这个主机内互联环上的一个计算节点,每个节点都有一个前向和一个后向,它只会向它的前向接收数据,并向它的右向发送数据,如下图所示,8张XPU 通过主机内的私有互联网络组成一个环,当然因为这些通信网络是双工的,这8张XPU训练加速卡也可以看成是通过多个逻辑环互联起来的,同时缺点是,如果这个ring太大,Ring Allreduce的效率也会变得很低。

ring拓扑

Ring Allreduce 有两种组合实现策略:1)先Reduce后broadcast;2)先ScatterReduce后AllGather,这两个策略执行后都会让每个XPU节点得到一样的平均梯度,如下图所示:

allreduce

3.1.1 Reduce +broadcast

在Reduce + broadcast里,reduce先将8张卡的梯度reduce sum到master节点 XPU0 上,再通过broadcast将这个总的平均梯度复制给其他XPU,如下图:

ring reduce broadcast

Reduce + broadcast这种策略有几个比较大的缺点:1)8张卡的数据都reduce sum到一张卡,假设每张卡的梯度是100MB,8张卡就是800MB,这可能存在XPU 0计算很久,而其他7张卡空闲的情况存在,整体效率不高;2)XPU0 的网络带宽可能会成为瓶颈,8张卡的数据都只能通过XPU0的互联网络进行reduce和broadcast,在数据量比较大的场景 XPU0的带宽成为瓶颈;3)8张XPU不都是两两全互联的,因此,要把8张卡的数据一次Reduce或broadcast,这一点受限于网络互联条件做不到,那么就需要采用 ring或tree的策略进行reduce或broadcast,这样效率也不高。

3.1.2 ScatterReduce + AllGather

Ring AllReduce 的Ring ScatterReduce + Ring AllGather策略组合里,每个 XPU只会从前向接受数据,并发送数据给后向,其算法主要分为:

  • ScatterReduce:这一步会先scatter拆分数据块再进行reduce,并且在执行完毕后,每张XPU都会包括一个完整的经过融合的同维梯度;
  • AllGather:这一步会进行全局Gather同步,最后所有 XPU都会得到完整的大的整个梯度;

Ring ScatterReduce + Ring AllGather是效率比较高的 Ring AllReduce 组合策略,这个策略考虑到了XPU上的梯度可能很大的情况,比如一个梯度有400MB,在scatterreduce阶段就会先被拆分成 ring上XPU个数份,比如主机内XPU个数等于8,那么 这400MB 就会被 拆分成8份,每份50MB,从而减少了加速卡的计算量以及节约带宽。此外,scatterReduce通过将数据拆分成小块,同时并发进行scatterReduce,从而将通信时间隐藏在计算时间内进而提高Ring AllReduce的效率。

3.1.2.1 ScatterReduce

首先, ScatterReduce先将梯度拆分为N个更小的块,N等于ring里XPU个数,8张卡就拆分成8份,然后进行N-1次scatterreduce迭代。在第一轮迭代中XPU 0上的A0传递给XPU1上A1并相加,XPU1上的B1传递给XPU2上的B2并相加,XPU 2上的C2传递给XPU3上C3并相加,XPU3上的D3传递给XPU4上的D4并相加,以此类推,过程如下图左侧:

ring acatterreduce

接下来,XPU还会进行N-2次 ScatterReduce 迭代,在每次迭代过程中,XPU都会从前向接收一个小梯度块并累加到自己的梯度块中,并且也会向其后向发送一个小梯度块,每个XPU接收和发送的小梯度块在每次迭代中都是不同的,这样经过迭代,到最后,每个XPU将有一个完整的同维梯度,该块梯度中包含所有XPU中该块对应的所有梯度的总和,如上图右侧的累加和部分。

3.1.2.2 Allgather

在scatterReduce迭代完成之后,每个XPU都会得到一个同维度的完整的梯度累加值,将这些完整的累加值复制到其他的加速卡后,才算完成allReduce。Allgather的迭代次数与scatterReduce是相同的,也都需要进行N-1次(N是ring上的XPU卡数)迭代,但是不同于ScatterReduce的是allGather没有reduce的过程,只有数值的复制。这样迭代到最后,每个XPU都得到大的拆分前的梯度的完整累加值,如下图演示了这一过程,从第一次迭代开始,到最后AllGather拿到整体的结果。这里头的具体过程就不在这里描述了,可以查相关资料。

image-20220409203458896

Ring AllReduce 实现简单,在ring较少时,效率也较高,但是在ring比较大时需要的网络节点跳数变得比较大,通信时延增加,因此效率也会降低。比如,一个1000张XPU的 ring,这里头网络的跳数 是N-1= 1000-1 =999, 同时传输的过程中,传输效率还受效率最低、带宽最低的XPU的限制,这时网络上的时延会变得巨高,这个时候ring allreduce拓扑算法就变得不大适用这个场景,同时如果在异构网络里涉及网络的不同连接方式,Ring AllReduce也不大适合使用,因此就需要采用另外的更适合网络结构的更高效的集合通信拓扑算法来进行优化。

3.2 2D-Ring AllReduce

如果一台2.1里的服务器只配置了一张RDMA网卡,每台服务器通过RDMA交换机互联,这个集群的网络是异构的(如下图),那么Ring AllReduce拓扑算法就不适用了,这个时候,对于这个网络拓扑结构比较适合的是2D-Ring AllReduce也叫Hierarchical Ring AllReduce。

2D-RING 拓扑

经过抽象,可以将这个网络结构表达成如下的Torus结构:

横向:每台服务器8个XPU节点,每个XPU节点通过私有协议网络互联;

纵向:每台服务器通过一张RDMA网卡NIC 0 通过交换机互联,这个网卡NIC0 与XPU0 挂在同一个PCIE switch上,满足具备亲和性条件,XPU0上的梯度可以通过NIC 0 与其他服务器上的XPU进行全局规约。

2D-RING TOPO

2D-Ring AllReduce的过程如下图所示:

2D-RING allreduce

第1步,先进行主机内Ring AllReduce,也可以是 Ring Reduce或者根据主机内的互联情况选用的分层reduce方式,将8张卡上的梯度累加到Master节点 XPU0 上;

第2步,进行主机间XPU 0的 Ring AllReduce,将每台服务器的XPU0上的数据进行全局规约;

第3步,进行主机内Broadcast,将XPU0上的梯度复制到服务器内的其他XPU上

2D-Ring AllReduce能充分发挥异构网络的优势,将主机内、主机间的网络带宽充分利用起来。但是XPU的利用率也不是很高,比如在做主机间的Ring AllReduce,每台服务器内的其他7张XPU是处于空闲状态的。

再假设,如果每台服务器配置了 2张/4张/8张RDMA网卡,这个时候 2D-RING AllReduce又难以将网络的优势发挥出来,那么就需要选用 2D-Torus/2D-Mesh AllReduce拓扑算法。

3.3 2D-Torus AllReduce

考虑到服务器内PCIE SWITCH 的亲和性问题,2D-Torus至少需要配备2张 左右对称的RDMA网卡才能发挥这个拓扑算法的优势。在这个集群里主机内每张卡都通过私有的通信协议组成Ring,而主机间,可以通过RDMA网卡(包括虚拟化出来的)与RDMA交换机将XPU两两互联,这个网络也是异构的,如下图所示:

设备互联拓扑

经过抽象,可以将这个网络结构表达成如下的Torus结构:

  • 横向:每台服务器8个XPU节点,每个XPU节点通过私有协议网络互联;
  • 纵向:每台服务器通过至少2张RDMA网卡NIC 0 /NIC 1通过交换机互联,这个网卡NIC0 与XPU0、1、2、3 挂在同一个PCIE switch上,具备亲和性条件,XPU0、1、2、3上的梯度数据可以通过NIC 0 与其他服务器上的XPU进行交换。网卡NIC1 与XPU4、5、6、7 挂在同一个PCIE switch上,具备亲和性条件,XPU4、5、6、7上的梯度数据可以通过NIC 1 与其他服务器上的XPU进行交换;
  • 当然如果网卡是4个或者8个,也可以根据PCIE SWITCH的亲和性情况合理安排XPU与NIC的对应关系。

2D 拓扑

2D-Torus AllReduce的过程如下图所示:

2dtorus allreduce

第1步,横向,先进行主机内Ring ScatterReduce,将主机内8张卡上的梯度进行拆分与规约,这样经过迭代,到最后每个XPU将有一个完整的同维梯度,该块梯度包含所有XPU中该块所对应的所有梯度的总和(参考3.1.2.1 scatterReduce)

第2步,纵向,进行主机间N个(N等于服务器内XPU个数,这里是8个)纵向的 Ring AllReduce,将每台服务器的XPU0-XPU7上的数据进行集群内纵向全局规约;

第3步,横向,进行主机内AllGather,将XPUi(i=0-7)上的梯度复制到服务器内的其他XPU上;

2D-Torus AllReduce能充分挖掘XPU的效率以及发挥异构网络里多网卡的优势,将XPU以及主机内、主机间的网络带宽优势充分利用起来。此外,除了 2D-Torus AllReduce外,2D-Mesh AllReduce也能发挥类似效率。

3.4 2D-Mesh AllReduce

2D-Mesh AllReduce的主要思想也是分层,与2D-Torus AllReduce类似,都是水平和垂直两个方向,但是有点差异,如下图所示:

2D-MESH allreduce

不同于2D-Torus AllReduce的拓扑算法,2D-Mesh AllReduce 过程是:

第1步,横向,先进行主机内Ring AllReduce 将主机内的8张XPU的梯度都进行规约;

第2步,纵向,进行主机间N个(N等于主机内XPU个数,这里是8个)纵向的 Ring AllReduce;

经过这两步,完成了整体的梯度累加,2D-Mesh AllReduce 也能充分发挥XPU与多网卡异构网络的优势,将XPU与主机内、主机间的网络带宽优势充分利用起来。这里的2D-Mesh与Google论文上的有点差异,主要是吸取了其分层的思想而不是复制其一样的设计。理论上2D-Mesh AllReduce对比 2D-Torus AllReduce,主机间AllReduce用的是 主机内8卡的全局梯度,数据量会比ScatterReduce部分来的大点,因此效率也会相应降低一点。

4. 问题探讨

如下图所示,基于Torus网络的结构,组合Ring AllReduce,2D-Ring AllReduce, 2D-Mesh AllReduce,2D-Torus AllReduce还能构建 3D-Ring/Mesh/Torus AllReduce拓扑算法,但是这些拓扑算法的效率需要进行实践才能证实,也许在规模较大的集群里才能发挥出3D 拓扑算法的优势。

2D-Torus拓扑

关于 3D-Ring/Mesh/Torus AllReduce的拓扑算法,这里就不在阐述,可作为研究使用。

5. 小结

本文讲述了分布式训练里最常用的几个网络结构以及通信拓扑算法:

  • Ring AllReduce 的最佳组合是 ScatterReduce + AllGather;
  • 2D-Ring AllReduce = 主机内 ringAllReduce/Ring Reduce +主机间 RingAllReduce + 主机内Broadcast;
  • 2D-Torus AllReduce = 主机内 Ring ReduceScatter + 主机间N个Ring AllReduce + 主机内Ring AllGather;
  • 2D-Mesh AllReduce = 主机内Ring AllReduce + 主机间N个Ring AllReduce;

Ring AllReduce适合主机内互联Ring的情况使用,2D-Ring AllReduce适合一台服务器配置了一张网卡的异构网络场景,2D-Torus AllReduce与2D-Mesh AllReduce适合一台服务器配置了2/4/8张网卡的异构网络场景。

集合通信拓扑算法多种多样,但基于成本以及效率的取舍考虑,可生产适用的其实也不多,除了理论上的理解之外更重要的是自己编写代码去实践落地。除此之外,还需要解决网络带宽有限、网络容易出故障、落后者效应、部署约束、多租户等产品化的质量要求。日拱一卒,功不唐捐,分享是最好的学习,与其跟随不如创新,希望这个知识点对大家有用。另作者能力与认知都有限,”我讲的,可能都是错的“,欢迎大家拍砖留念。

6. 作者简介

常平,中科大硕,某AI芯片公司深度学习高级软件主管、架构师,前EMC资深首席工程师,主要工作背景在深度学习、Ai平台、系统调优、大数据、云计算以及Linux内核领域。

7. 参考资料

[1] https://www.changping.me

[2] 《volta-architecture-whitepaper》

[3] 2D-HRA: Two-Dimensional Hierarchical Ring-based All-reduce Algorithm in Large-Scale Distributed Machine Learning

[4] Massively Distributed SGD: ImageNet/ResNet-50 Training in a Flash

[5] https://zhuanlan.zhihu.com/p/79030485 , 腾讯机智团队分享–AllReduce算法的前世今生

[6] https://zhuanlan.zhihu.com/p/370548366, ring allreduce和tree allreduce的具体区别是什么?

[7] https://zhuanlan.zhihu.com/p/184942777 , 分布式深度学习初探

[8] https://arxiv.org/abs/1811.06992 , Image Classification at Supercomputer Scale

8. 版权申明

本文的版权协议为 CC-BY-NC-ND license:https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh

在遵循署名、非商业使用(以获利为准)以及禁止演绎的前提下可以自由阅读、分享、转发、复制、分发等。

1. 概述

集合通信(Collective Communications)是一个进程组的所有进程都参与的全局通信操作,其最为基础的操作有 发送send、接收receive、复制copy、组内进程栅障同步Barrier以及节点间进程同步(signal +wait ),这几个最基本的操作经过组合构成了一组通信模板也叫通信原语,比如:1对多的广播broadcast、多对1的收集gather、多对多的收集all-gather、1对多的发散scatter、多对1的规约reduce、多对多的规约all-reduce、组合的规约与发散reduce-scatter、多对多的all-to-all等,集合通信的难点在于通信效率以及网络硬件连接拓扑结构的最佳适用。

2. 通信原语

以一台集成了4张训练加速卡的服务器为例,如下图,服务器内四张训练加速卡是全连接的,物理连接方式可以是私有物理互联协议,比如CXL、NVLINK,也可以是PCIe、InfiniBand、Ethernet等,本文将以此物理拓扑结构描述集合通信中常用的几组通信原语。

image-connect-topo

2.1 Broadcast

Broadcast属于1对多的通信原语,一个数据发送者,多个数据接收者,可以在集群内把一个节点自身的数据广播到其他节点上。如下图所示,圈圈表示集群中的训练加速卡节点,相同的颜色的小方块则代表相同的数据。当主节点 0 执行Broadcast时,数据即从主节点0被广播至其他节点。

image-20220404193446314

Broadcast是数据的1对多的同步,它将一张XPU卡上的数据同步到其他所有的XPU卡上,其应用场景有:

1)数据并行的参数初始化,确保每张卡上的初始参数是一致的;

2)allReduce里的 broadcast + reduce组合里的broadcast操作;

3)分布式训练parameter server 参数服务器结构里的 master节点 broadcast 数据到worker节点,再从worker节点reduce数据回master节点里的broadcast操作;

2.2 Scatter

同Broadcast一样,Scatter也是一个1对多的通信原语,也是一个数据发送者,多个数据接收者,可以在集群内把一个节点自身的数据发散到其他节点上。与Broadcast不同的是Broadcast把主节点0的数据发送给所有节点,而Scatter则是将数据的进行切片再分发给集群内所有的节点,如下图所示,不相同的颜色的小方块代表不相同的数据,主节点 0 将数据分为四份分发到了节点0-3。

image-20220404193446314

Scatter是数据的1对多的分发,它将一张XPU卡上的数据进行分片再分发到其他所有的XPU卡上,他的反向操作对应Gather,其应用场景有:

1)ReduceScatter组合里的 Scatter操作;

2)模型并行里初始化时将模型scatter到不同的XPU上;

2.3 Gather

Gather操作属于多对1的通信原语,具有多个数据发送者,一个数据接收者,可以在集群内把多个节点的数据收集到一个节点上,如下图所示,不相同的颜色的小方块代表不相同的数据。

image-20220404193952158

Gather是数据的多对1的收集,它将多张XPU卡上的数据收集到1张XPU卡上,他的反向操作对应Scatter,其应用场景有:

1)ReduceScatter组合里的 Scatter操作;

2.4 AllGather

AllGather属于多对多的通信原语,具有多个数据发送者,多个数据接收者,可以在集群内把多个节点的数据收集到一个主节点上(Gather),再把这个收集到的数据分发到其他节点上(broadcast),即收集集群内所有的数据到所有的节点上。

image-20220404194323067

AllGather是数据的多对多的同步全收集,它将多张XPU卡上的数据收集到多张XPU卡上,可以看做Gather + Broadcast的操作组合,它的反向操作对应ReduceScatter,其最应用场景有:

1) AllGather可应用于模型并行;

2)模型并行里前向计算里的参数全同步,需要用allgather把模型并行里将切分到不同的XPU上的参数全同步到一张XPU上才能进行前向计算。

2.5 Reduce

Reduce属于多对1的通信原语,具有多个数据发送者,一个数据接收者,可以在集群内把多个节点的数据规约运算到一个主节点上,常用的规约操作符有:求累加和SUM、求累乘积PROD、求最大值MAX、求最小值MIN、逻辑与 LAND、按位与BAND、逻辑或LOR、按位或BOR、逻辑异或LXOR、按位异或BOXR、求最大值和最小大的位置MAXLOC、求最小值和最小值的位置MINLOC等,这些规约运算也需要加速卡支持对应的算子才能生效。

Reuduce操作从集群内每个节点上获取一个输入数据,通过规约运算操作后,得到精简数据,如下图的SUM求累加和:节点0数值 5、节点1数值6、节点2数值7、节点3数值8,经过SUM运算后 累积和为 26,即得到更为精简的数值,在reduce原语里回会去调用 reduce SUM算子来完成这个求和累加。

image-20220404194633808

Reduce是数据的多对1的规约运算,它将所有张XPU卡上的数据规约(比如SUM求和)到1张XPU卡上,其应用场景有:

1)AllReduce里的 broadcast + reduce组合里的reduce操作;

2)ReduceScatter组合里的 reduce操作;

3)分布式训练parameter server 参数服务器结构里的 master节点 broadcast 数据到worker节点,再从worker节点reduce数据回master节点里的reduce操作;

2.6 ReduceScatter

ReduceScatter属于多对多的通信原语,具有多个数据发送者,多个数据接收者,其在集群内的所有节点上都按维度执行相同的Reduce规约运算,再将结果发散到集群内所有的节点上,Reduce-scatter等价于节点个数次的reduce规约运算操作,再后面执行节点个数的scatter次操作,其反向操作是AllGather。

如下图所示,先reduce操作 XPU 0-3的数据reduce为 A(A0+A1+A2+A3) + B(B0 + B1 +B2 + B3) + C(C0 + C1 + C2 + C3) + D(D0 + D1 + D2 + D3 ) 到一张XPU上,再进行分片scatter到集群内所有的XPU卡上。

image-20220404200227476

ReduceScatter是数据的多对多的reduce + scatter运算,它将所有的XPU卡上的数据先规约(比如SUM求和)到1张XPU卡上,再进行scatter,其应用场景有:

1)ReduceScatter即可应用于数据并行也可应用于模型并行;

2)数据并行allReduce里的 ReduceScatter+ Allgather组合里的ReduceScatter操作;

3)模型并行里在前向allgather后的反向计算里的ReduceScatter;

2.7 AllReduce

AllReduce属于多对多的通信原语,具有多个数据发送者,多个数据接收者,其在集群内的所有节点上都执行相同的Reduce操作,可以将集群内所有节点的数据规约运算得到的结果发送到所有的节点上。AllReduce操作可通过在主节点上执行Reduce + Broadcast或ReduceScatter + AllGather实现,如下图所示:先在主节点上执行reduce得到规约累加和26,再把这个累加和26 broadcast到其他的节点,这样整个集群内,每个节点的数值就都保持一致。

image-20220404195550358

AllReduce是数据的多对多的规约运算,它将所有的XPU卡上的数据规约(比如SUM求和)到集群内每张XPU卡上,其应用场景有:

1) AllReduce应用于数据并行;

2)数据并行各种通信拓扑结构比如Ring allReduce、Tree allReduce里的 allReduce操作;

2.8 All-To-All

All-To-All操作每一个节点的数据会scatter到集群内所有节点上,同时每一个节点也会Gather集群内所有节点的数据。ALLTOALL是对ALLGATHER的扩展,区别是ALLGATHER 操作中,不同节点向某一节点收集到的数据是相同的,而在ALLTOALL中,不同的节点向某一节点收集到的数据是不同的,如下图所示

image-20220404202332268

AllToAll是数据的多对多的转置,它将所有张XPU卡上的数据转置到所有的XPU卡上,其主要应用场景有:

1) AllToAll应用于模型并行;

2)模型并行里的矩阵转置;

3)数据并行到模型并行的矩阵转置;

2.9 Send 与 Receive

数据或参数在不同XPU之间的发送与接收。

2.10 Barrier

BARRIER同步操作会阻塞所有的调用者直到所有的组内成员都调用了它, 用于一个集合通信子中所有进程的同步,调用函数时进程将处于等待状态,直到通信子中所有进程 都调用了该函数后才继续执行。

2.11 Signal与Wait

Signal与Wait属于记录型信号量机制: wait(s),signal(s)可用于解决进程间的同步问题,在通信原语里从一个节点发送一个数据到另外一个节点时,会同时signal一个event值到对端,对端的wait操作接收到这个event时会返回一个确认给signal,这样保证在节点的进程间进行数据的同步操作。

3. 小结

在分布式训练过程中,深度学习训练框架不会去直接操作底层的通信网络,而是通过使用网络通信库来完成数据的集合通信,各家AI芯片加速卡厂家都会提供私有的网络通信库比如:xxx-AWARE OpenMPI或xCCL来完成这个底层通信硬件的屏蔽与抽象。在分布式训练集群里网络通信硬件连接样式多种多样,可以是Ethernet、InfiniBand 、RoCE v2/v1 等也可以是CXL、NVLINK等私有协议,这就要求在通信的后端层根据各个厂家的自己的SDK开发库接口,根据实际情况实现 各自的网络通信库,比如cuda-aware MPI、NCCL、NVSHMEM,以及根据实际的网络拓扑组合完成对应的最有效的网络拓扑算法。

本文讲述了分布式训练里的集合通信原语,这些原语是集合通信拓扑算法的基本组成单元,后续的文章里会讲述如何组合这些通信原语以完成合适的通信拓扑算法。日拱一卒,功不唐捐,分享是最好的学习,与其跟随不如创新,希望这个知识点对大家有用。另作者能力与认知都有限,”我讲的,可能都是错的“,欢迎大家拍砖留念。

4. 作者简介

常平,中科大硕,某AI芯片公司深度学习高级软件主管、架构师,前EMC资深首席工程师,主要工作背景在深度学习、Ai平台、系统调优、大数据、云计算以及Linux内核领域。

5. 参考资料

[1] https://www.changping.me

[2] http://scc.ustc.edu.cn/zlsc/cxyy/200910/MPICH

[3] 《用这拌元宵,一个字:香!| 分布式训练硬核技术——通讯原语》

[4] 《NCCL-Woolley》

[5] 《利用MegEngine分布式通信算子实现复杂的并行训练》

6. 版权申明

本文的版权协议为 CC-BY-NC-ND license:https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh

在遵循署名、非商业使用(以获利为准)以及禁止演绎的前提下可以自由阅读、分享、转发、复制、分发等。