# 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

> **说明:**
>图中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)所示。
> **说明:**
>- 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

图中关键步骤说明如下:
1. 获取task的昇腾910 AI处理器申请数量。
2. 根据请求的昇腾910 AI处理器数量,按照[资源申请约束](#"亲和性策略说明")选出最优的节点。
3. 从选出的节点中,选择符合要求的昇腾910 AI处理器。
4. 对选出的结果进行保存。
5. 对选出的节点进行加权操作。
> **说明:**
>[1](#li2081354582012)\~[5](#li205713218818)都是在Volcano提供的注册函数batchNodeOrderFn中实现。
6. 对选出的节点进行资源分配管理。
> **说明:**
>该步骤是在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\)
-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组件二进制文件
|
> **说明:**
>_\{__version__\}_:表示版本号。
## 安装前准备和安装Volcano
请参考《[MindX DL用户指南](https://www.hiascend.com/software/mindx-dl)》中的“集群调度用户指南 \> 安装部署指导 \> 安装集群调度组件 \> 典型安装场景 \> 集群调度场景”进行。
版本更新记录
版本
|
发布日期
|
修改说明
|
v3.0.0
|
2023-01-18
|
- 开源首次发布。
- 具体内容请参考《MindX DL用户指南》
|