# ascend-for-volcano **Repository Path**: zhaozepeng/ascend-for-volcano ## Basic Information - **Project Name**: ascend-for-volcano - **Description**: 基于开源Volcano,增强华为NPU亲和性调度功能。 - **Primary Language**: Go - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 46 - **Created**: 2023-09-12 - **Last Updated**: 2023-09-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README t # NPU亲和性调度算法设计说明与开发指导.zh - [Ascend-volcano-plugin介绍](#Ascend-volcano-plugin介绍文档) - [亲和性策略说明](#亲和性策略说明文档) - [调度算法设计说明](#调度算法设计说明文档) - [调度算法实现说明](#调度算法实现说明文档) - [目录结构](#目录结构文档) - [编译说明](#编译说明文档) - [版本更新记录](#版本更新记录文档)

Ascend-volcano-plugin介绍

基于开源Volcano调度的插件机制,增加昇腾处理器的亲和性调度,虚拟设备调度等特性,最大化发挥昇腾处理器计算性能。

亲和性策略说明

## 昇腾910 AI处理器亲和性规则 昇腾910 AI处理器是华为研发的一款高性能AI处理器。其内部的处理器之间采用HCCS方式连接。每台物理设备具备8颗处理器,两个HCCS。每个HCCS存在4颗处理器,同一HCCS内处理器可做数据交换,不同HCCS内处理器不能通信,即同一Pod分配的昇腾910 AI处理器(若小于等于4)必须在同一个HCCS环内,否则任务运行失败。昇腾910 AI处理器的互联拓扑图如[图1](#fig997414281914)所示。 **图 1** Ascend 910 AI Processor interconnection topology ![](doc/figures/Ascend-910-AI-Processor-interconnection-topology.png "Ascend-910-AI-Processor-interconnection-topology") >![](doc/figures/icon-note.gif) **说明:** >图中A0\~A7为昇腾910 AI处理器。 ## 亲和性策略说明 针对昇腾910 AI处理器的特征和资源利用的规则,制定昇腾910 AI处理器的亲和性策略如[表1](#table644103781119)所示。 **表 1** 昇腾910 AI处理器亲和性策略说明

优先级

策略名称

详细内容

1

HCCS亲和性调度原则

  • 如果申请昇腾910 AI处理器个数为1,则选择同一HCCS,剩余可用的昇腾910 AI处理器数量为1个的最佳,其次是剩余3个的为次佳,然后是剩余2个,最后是剩余4个。
  • 如果申请昇腾910 AI处理器个数为2,则选择同一HCCS剩余可用的昇腾910 AI处理器数量2个的为最佳,其次是剩余4个,最后是剩余3个。
  • 如果申请昇腾910 AI处理器个数为4,则必须选择同一HCCS剩余可用的昇腾910 AI处理器数量为4个。
  • 如果申请昇腾910 AI处理器个数为8,则申请节点所有8个昇腾910 AI处理器

2

优先占满调度原则

优先分配已经分配过昇腾910 AI处理器的AI服务器,减少碎片。

  • 如果申请1个昇腾910 AI处理器,优先申请capacity为8,且HCCS剩余可用处理器数量为1的节点,然后是剩余可用数量为3个,2个,4个。
  • 如果申请2个昇腾910 AI处理器,优先申请capacity为8,且HCCS剩余可用处理器数量为2的节点,然后是剩余可用数量为4个,3个。
  • 如果申请4个昇腾910 AI处理器,优先申请capacity为8,且剩余可用处理器数量为4的节点。
  • 如果申请昇腾910 AI处理器为8的正整数倍数,申请capacity为8,且已使用0个处理器的节点。

3

剩余偶数优先原则

优先选择满足1~3条件的HCCS,然后选择剩余处理器数量为偶数的HCCS。

--

多节点支持原则

一次训练任务只支持8*N的方式分配。

## 资源申请约束 根据业务模型,对训练任务的要求如下: 1. 当训练任务申请昇腾910 AI处理器数量不大于4个时,需要将所需的昇腾910 AI处理器调度到同一个HCCS内。 2. 当训练任务申请的昇腾910 AI处理器数量为8个时,需要将节点的昇腾910 AI处理器分配给该任务。 3. 当申请的NPU数量大于8个时,申请数量只能是8\*N(N\>=1)个。 4. 当训练任务申请的昇腾910 AI处理器数量不大于8时,只能申请一个Pod。大于8则每个Pod为8个昇腾910 AI处理器。 5. 当训练任务申请虚拟设备vNPU时,申请数量只能为1。 6. 遵循Volcano开源部分的其他约束。

调度算法设计说明

## 场景分类 根据亲和性策略和业务模型设计梳理出场景如[表1](#table34241172175)所示。 >![](doc/figures/icon-note.gif) **说明:** >- A\~D列4个分组,表示处理器选取时,满足处理器选取的四种HCCS情况。优先级逐次递减,即当A中不满足时,才会选择B,C,D。 >- 当组内满足HCCS时节点的情况。‘\~’左边为满足要求的HCCS,右边为另一个HCCS的处理器剩余情况。如对于1个处理器申请的A组情况:另一个HCCS可能为0、1、2、3、4五种处理器剩余情况。其代表的节点优先级也依次减小。 >- 8颗及其以上处理器适用于4颗及其以下的情况。且均放在A组,且需要全部占用。 **表 1** 亲和性策略场景列表

场景序号

任务申请芯片数

A(节点中处理器剩余数)

B

C

D

备注

1

1

1~[0、1、2、3、4]

3~[0、2、3、4]

2~[0、2、4]

4~[0、4]

然后选择capacity为7,坏的视为已使用,重复A~D

2

2

2~[0、1、2、3、4]

4~[0、1、3、4]

3~[0、1]

-

3

4

4~[0、1、2、3、4]

-

-

-

4

8

8

-

-

-

-

5

8*N

0(8个处理器全部被占用)

-

-

-

-

## 算法设计说明 **图 1** Affinity algorithm design process ![](doc/figures/Affinity-algorithm-design-process-ch.png "Affinity-algorithm-design-process") 图中关键步骤说明如下: 1. 获取task的昇腾910 AI处理器申请数量。 2. 根据请求的昇腾910 AI处理器数量,按照[资源申请约束](#"亲和性策略说明")选出最优的节点。 3. 从选出的节点中,选择符合要求的昇腾910 AI处理器。 4. 对选出的结果进行保存。 5. 对选出的节点进行加权操作。 >![](doc/figures/icon-note.gif) **说明:** >[1](#li2081354582012)\~[5](#li205713218818)都是在Volcano提供的注册函数batchNodeOrderFn中实现。 6. 对选出的节点进行资源分配管理。 >![](doc/figures/icon-note.gif) **说明:** >该步骤是在Volcano的AddEventHandler函数中实现。该函数包含了节点资源的预分配allocate函数。 7. 完成以上的分配操作后,Volcano框架会将本轮分配结果提交给K8s的kubelet进行确认执行,本次分配结束。 ## 多节点处理原则 该特性结合Volcano的集群设计,只需要利用框架在选取节点时对每个节点进行加权,取出最优者即可。 两阶段的选取:先选出4个优选数组,再进行组内选取,最终实现多节点的整体考虑。 ## 并发处理原则 由于Volcano未在allocate阶段的add方法中提供函数回调方法,故对于处理器的选取在节点筛选阶段就进行了。这样做的影响是:在任务并发执行时,可能存在芯片重复分配的情况。 以下两种场景可能涉及重复分配: - 本session的不同任务间。当多个任务同时需要分配,且同一节点可以分给多个任务时。由于原生Volcano只是对数量进行分配,未对处理器编号进行分配。会造成处理器总数分配完成,出现某一处理器被分配多次的情况。 本程序使用Volcano框架提供的AddEventHandler函数来解决。在函数的allocate方法中,实现对节点处理器分配情况的管理。从而避免了重复分配的情况。 - 不同session之间。在本次session分配处理器时,由于在加权阶段就进行了分配,若此时资源处于等待释放状态,即暂时不能分配,就会出现本次分配失败。但Volcano在本次session不会感知。下次session时,该处理器变为可分配状态,会分配给其他任务。导致两个任务分配到同一个处理器,其中一个任务失败。 解决该问题的方法之一:在加权阶段进行处理器分配时,判断资源是否处于待释放状态。若是,则本次不分配。

调度算法实现说明

## 程序流程设计说明 **图 1** Affinity program process \(Volcano part\) ![](doc/figures/Affinity-program-process-(Volcano-part)-ch.png "Affinity-program-process-(Volcano-part)") 华为昇腾处理器的亲和性调度基于Volcano开源部分提供的的插件机制,实现了插件简化开发。过程中主要实现了volcano-schedule框架中的几个插件函数。当Volcano每次session运行时,实现的函数就会按照编写的规则运行,从而实现处理器的亲和性调度。亲和性调度插件主要实现的函数如下: - validJobFn: 该函数主要是拦截申请NPU资源的任务,但申请的数量需要满足亲和性策略。具体要求请参见[亲和性策略说明](#"亲和性策略说明")。 - AddPredicateFn: 该函数主要是过滤掉不满足亲和性要求的节点。比如task请求数量为2时,但节点的两个HCCS却各自拥有1个处理器。该节点满足数量要求,却不满足亲和性要求,需要排除。 - AddBatchNodeOrderFn: 该函数主要是选出满足亲和性条件的节点和节点内的处理器,并将结果放入Pod中。 - AddEventHandler: 该函数主要是将节点拥有的可用的昇腾910 AI处理器进行统一管理。防止并发情况下的分发错误。

目录结构

``` ├── build # CI编译脚本 │ ├── build.sh # CI构建二进制脚本 │ └── testBuild.sh # LLT测试启动脚本 ├── doc # 说明文档 │ └── figures │ ├── Affinity-algorithm-design-process-ch.png │ ├── Affinity-algorithm-design-process-en.png │ ├── Affinity-program-process-(Volcano-part)-ch.png │ ├── Affinity-program-process-(Volcano-part)-en.png │ ├── Ascend-910-AI-Processor-interconnection-topology.png │ ├── icon-caution.gif │ ├── icon-danger.gif │ ├── icon-note.gif │ ├── icon-notice.gif │ ├── icon-tip.gif │ └── icon-warning.gif ├── huawei_npu.go # ascend-volcano-plugin组件入口代码 ├── huawei_npu_test.go ├── internal │ ├── ascend310 │ │ ├── card310x4 # 310卡调度策略代码目录 │ │ │ ├── frame.go │ │ │ ├── frame_test.go │ │ │ ├── task.go │ │ │ └── type.go │ │ ├── chip310x4 # 310 芯片调度策略代码目录 │ │ │ ├── frame.go │ │ │ ├── frame_test.go │ │ │ ├── node.go │ │ │ └── type.go │ │ ├── frame.go │ │ ├── frame_test.go │ │ └── type.go │ ├── ascend310p # 310P 卡调度公共代码目录 │ │ ├── frame.go │ │ ├── frame_test.go │ │ ├── rescheduling.go │ │ ├── type.go │ │ ├── vnpu.go │ │ └── vnpu_test.go │ ├── ascend910 │ │ ├── card910x2 # A300T调度策略代码目录 │ │ │ ├── frame.go │ │ │ ├── frame_test.go │ │ │ ├── job.go │ │ │ └── type.go │ │ ├── frame.go │ │ ├── frame_test.go │ │ ├── half910x4 # 800/9000 4卡调度策略代码目录 │ │ │ ├── frame.go │ │ │ ├── frame_test.go │ │ │ ├── job.go │ │ │ ├── node.go │ │ │ └── type.go │ │ ├── module910x8 # 800/9000调度策略代码目录 │ │ │ ├── frame.go │ │ │ ├── frame_reschedule_test.go │ │ │ ├── frame_test.go │ │ │ ├── job.go │ │ │ ├── node.go │ │ │ ├── task.go │ │ │ └── type.go │ │ └── type.go │ ├── base # 基础调度策略代码目录 │ │ ├── frame.go │ │ ├── frame_test.go │ │ ├── node.go │ │ ├── task.go │ │ └── type.go │ ├── rescheduling # 故障调度策略代码目录 │ │ ├── cache.go │ │ ├── cache_test.go │ │ ├── configmap.go │ │ ├── configmap_test.go │ │ ├── frame_reschedule_test.go │ │ ├── job.go │ │ ├── job_test.go │ │ ├── node.go │ │ ├── node_test.go │ │ ├── reschedule.go │ │ ├── reschedule_test.go │ │ ├── task.go │ │ └── type.go │ ├── test # LLT公共代码目录 │ │ ├── job.go │ │ ├── reschedule.go │ │ └── type.go │ └── vnpu # VNPU调度公共代码目录 │ ├── frame.go │ ├── node.go │ ├── pod.go │ ├── type.go │ ├── vdynamic.go │ └── vstatic.go ├── LICENSE ├── output # CI编译结果目录 │ ├── Dockerfile-controller │ ├── Dockerfile-scheduler │ └── volcano-v1.4.0.yaml ├── OWNERS ├── plugin # 插件适配代码目录 │ ├── device_info.go │ ├── device_info_test.go │ ├── factory.go │ ├── factory_test.go │ ├── job.go │ ├── job_test.go │ ├── node.go │ ├── node_test.go │ ├── plugin.go │ ├── plugin_test.go │ ├── task.go │ ├── task_test.go │ ├── type.go │ └── vnode.go ├── README.md ├── test # llt公共基础代码目录 │ ├── frame.go │ ├── job.go │ ├── node.go │ ├── pod.go │ ├── reschedule.go │ └── type.go ├── tree.txt ├── type.go └── util # 调度策略公共代码目录 ├── configmap.go ├── job.go ├── job_test.go ├── task.go ├── type.go └── util.go ```

编译说明

## 编译前准备 - 确保PC机连接至互联网,并已完成Git和Docker的安装。参见[Git安装](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git),[Docker-ce安装](https://docs.docker.com/engine/install/ubuntu/)。 - 已完成Go语言环境的安装(版本\>1.13,建议使用最新的bugfix版本)。参见[https://golang.org/](https://golang.org/)。 - 完成musl的安装(版本\>=1.2.0)。参见[http://musl.libc.org/](http://musl.libc.org/)。 - 根据所在网络环境配置Go代理地址,国内可使用**Goproxy China**,例如: ``` go env -w GOPROXY=https://goproxy.cn,direct ``` ## 编译Volcano 1. 执行以下命令,在“$GOPATH/src/volcano.sh/“目录下拉取Volcano v1.4.0(或v1.7.0)版本官方开源代码。 **cd** **$GOPATH/src/volcano.sh/** **git clone -b release-1.4 https://github.com/volcano-sh/volcano.git** 2. 将代码目录“ascend-for-volcano“重命名为“ascend-volcano-plugin”拷贝至Volcano官方开源代码的插件路径下(“$GOPATH/src/volcano.sh/volcano/pkg/scheduler/plugins/“)。 3. 执行以下命令,编译Volcano二进制文件和so文件。根据开源代码版本,为build.sh脚本选择对应的参数,如v1.4.0. **cd** **$GOPATH/src/volcano.sh/volcano/pkg/scheduler/plugins/ascend-volcano-plugin/build** **chmod +x build.sh** **./build.sh v1.4.0** 编译出的二进制文件和动态链接库文件在“ascend-volcano-plugin/output“目录下,文件[表1](#table922124765019)所示。 **表 1** output路径下的文件列表

文件名

说明

volcano-npu-{version}.so

Volcano华为NPU调度插件动态链接库

Dockerfile-scheduler

Volcano scheduler镜像构建文本文件

Dockerfile-controller

Volcano controller镜像构建文本文件

volcano-{version}.yaml

Volcano的启动配置文件

vc-scheduler

Volcano scheduler组件二进制文件

vc-controller-manager

Volcano controller组件二进制文件

>![](doc/figures/icon-note.gif) **说明:** >_\{__version__\}_:表示版本号。 ## 安装前准备和安装Volcano 请参考《[MindX DL用户指南](https://www.hiascend.com/software/mindx-dl)》中的“集群调度用户指南 \> 安装部署指导 \> 安装集群调度组件 \> 典型安装场景 \> 集群调度场景”进行。

版本更新记录

版本

发布日期

修改说明

v3.0.0

2023-01-18

  • 开源首次发布。
  • 具体内容请参考《MindX DL用户指南》