Skip to content

Commit

Permalink
zq/fix readme (DeepLink-org#1219)
Browse files Browse the repository at this point in the history
* fix readme

---------

Co-authored-by: yangbofun <[email protected]>
  • Loading branch information
NeosZhang and yangbofun authored May 21, 2024
1 parent 0c0613d commit 2e38394
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 35 deletions.
2 changes: 1 addition & 1 deletion Contributors.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ git push -u origin {branch_name}
-->
所有 reviewer 同意合入 PR 后,我们会尽快将 PR 合并到主分支。

(5) 当前只有IMPL文件夹支持开发者贡献代码,PROTO与DIOPI-TEST后续会逐步开放
(5) 当前只有impl文件夹支持开发者贡献代码,proto与diopi_test后续会逐步开放

#### 6. 解决冲突

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ DIOPI主要包含以下几个组件:
## 校验算子
1. 将数据拷贝到芯片机器上,执行以下命令验证算子:
1. 将生成的基准数据拷贝到芯片机器上,执行以下命令验证算子:
```
python main.py --mode gen_case # 生成pytest测例
python main.py --mode run_test # 执行测试
Expand Down
18 changes: 9 additions & 9 deletions diopi_test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<img src="../img/deepLink_logo.png">
</div>

# DIOPI_TEST
# diopi_test

DIOPI_TEST是构建于设备无关算子接口(Device-Independent Operator Interface, DIOPI)之上的测试框架,它支持了没有训练框架的情况下,验证算子适配正确性的功能。DIOPI_TEST设计了一套完整的测试框架和一套算子函数测试。测试套件,可以使芯片厂商适配 DIOPI 算子时,无需训练框架即可对适配结果的正确性进行验证。
diopi_test是服务于设备无关算子接口(Device-Independent Operator Interface, DIOPI)的测试框架,它支持在没有训练框架的情况下,验证算子适配正确性的功能。diopi_test设计了一套完整的测试框架和一套算子函数测试套件,可以使芯片厂商适配 DIOPI 算子时,无需训练框架即可对适配结果的正确性进行验证。

主要模块:
* DIOPI_TEST 运行时:支持了运行时函数的接口,用以管理设备相关资源。
* diopi_test 运行时:支持了运行时函数的接口,用以管理设备相关资源。
* 非算子测试:
* 测试获取设备相关信息标准接口。
* 测试获取错误信息标准接口。
Expand All @@ -21,9 +21,9 @@ DIOPI_TEST是构建于设备无关算子接口(Device-Independent Operator Int
* 从40多个模型训练过程中抓取张量形状,数据类型及其他非张量参数值生成测例。


DIOPI_TEST 测试范围:
diopi_test 测试范围:
* 每一个 DIOPI 标准算子均有相应的测试,并且会从不同的数据类型、张量维度、非张量参数等角度对每个算子设计多个测例。保证 DIOPI 标准算子接口中每个参数功能均被测试。针对常见训练算子目前已有约 11000+个测例, 其中涵盖了如 conv2d, batch_norm, adaptive_max_pool2d, relu 等经典训练算子。
* DIOPI_TEST 提供的模型算子测试,涵盖了经典分类模型如 resnet50, vgg16, seresnet50, densenet, mobilenet_v2, efficientnet, shufflenet_v2, repvgg, swin_transformer, vit, inceptionv3 及经典检测模型如 retinanet, faster_rcnn_r50, ssd300, yolov3, atss, fcos, mask_rcnn, solo, centernet, cascade_rcnn, detr 及经典分割模型如 unet, upernet, pspnet, fcn, deeplabv3, deeplabv3plus 及其他领域深度学习模型 sar, dbnet, stgcn, crnn, hrnet, deeppose, tsn, slowfast。
* diopi_test 提供的模型算子测试,涵盖了经典分类模型如 resnet50, vgg16, seresnet50, densenet, mobilenet_v2, efficientnet, shufflenet_v2, repvgg, swin_transformer, vit, inceptionv3 及经典检测模型如 retinanet, faster_rcnn_r50, ssd300, yolov3, atss, fcos, mask_rcnn, solo, centernet, cascade_rcnn, detr 及经典分割模型如 unet, upernet, pspnet, fcn, deeplabv3, deeplabv3plus 及其他领域深度学习模型 sar, dbnet, stgcn, crnn, hrnet, deeppose, tsn, slowfast。


## **使用教学**
Expand All @@ -45,7 +45,7 @@ python main.py --mode run_test --html_report
```

### 可选测试模式
DIOPI_TEST框架还提供针对不同硬件芯片特点的测试模式以及其他测试模式
diopi_test框架还提供针对不同硬件芯片特点的测试模式以及其他便于开发者使用的选项

* mode: 指定测试阶段

Expand Down Expand Up @@ -75,6 +75,7 @@ DIOPI_TEST框架还提供针对不同硬件芯片特点的测试模式以及其
python main.py --mode gen_data --fname relu
python main.py --mode gen_case --fname relu
python main.py --mode run_test
# 测试所有算子
python main.py --mode gen_data
python main.py --mode gen_case
Expand Down Expand Up @@ -149,7 +150,7 @@ DIOPI_TEST框架还提供针对不同硬件芯片特点的测试模式以及其
```
### 测例配置说明
DIOPI-TEST 设计了一套测例配置规则及相应的测试框架。以算子测试为例,所有算子测例配置文件位于 python/configs/diopi_configs.py 中。
diopi_test 设计了一套测例配置规则及相应的测试框架。以算子测试为例,所有算子测例配置文件位于 python/configs/diopi_configs.py 中。
我们以 group_norm 算子测例配置为例来阐释说明测例生成。
```
Expand Down Expand Up @@ -347,5 +348,4 @@ DIOPI-TEST 设计了一套测例配置规则及相应的测试框架。以算子
```
python main.py --mode gen_case --impl_folder /path/to/folder --fname cdist
python main.py --mode run_test
```
```
45 changes: 26 additions & 19 deletions impl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
</div>


# IMPL
# impl

IMPL 主要用于芯片厂商基于 PROTO 进行标准算子实现,芯片厂商可通过封装自身计算库或者调用 ``kernel`` 的方式来实现 PROTO 定义良好的标准算子接口以备后续测试调用和训练框架调用
impl 主要用于芯片厂商基于 proto 进行标准算子实现,芯片厂商可通过封装自身计算库或者调用 ``kernel`` 的方式来实现 proto 定义好的标准算子接口以备后续测试调用和训练框架调用

其价值体现在以实现统一接口计算库的形式,来对接不同训练框架。无需考虑不同训练框架特性,可更专注于提升每个功能性算子的性能。

其主要功能如下:
* 实现 PROTO 函数接口并编译生成计算库以供测试和训练框架调用
* 实现 proto 函数接口并编译生成计算库以供测试和训练框架调用


## **实现原理**

如果使用diopi_test来测试算子实现的正确性,则需要实现[diopi/proto/include/diopi/diopirt.h](../proto/include/diopi/diopirt.h)中的和厂商相关的runtime接口(通过注册的形式,详见下文)。
编译脚本在[scripts/build_imp.sh](scripts/build_impl.sh)其中-DTEST表示是否编译diopi_test测试所需要的代码。并且需要设置环境变量`-DTEST=ON`时,此时在编译时,会包含测试相关的代码,并生成供diopi_test使用的so文件。如果不设置环境变量`-DTEST=OFF`,则编译生成的so文件中没diopi_test所需要的so文件,此时可供上层框架调用(比如[DIPU](https://github.com/DeepLink-org/DIPU))。
#### 实现 TEST 所需运行时函数
编译脚本在[scripts/build_imp.sh](scripts/build_impl.sh)其中编译选项-DTEST表示是否编译diopi_test测试所需要的代码,如果设置为`-DTEST=ON`,则在编译时会包含测试相关的代码,并生成供diopi_test使用的so文件。如果设置为`-DTEST=OFF`,则编译生成的so文件中没diopi_test所需要的so文件,此时可供上层框架调用(比如[DIPU](https://github.com/DeepLink-org/DIPU))。
#### 实现 diopi_test 所需运行时函数

[diopi_test/include/conform_test.h](../diopi_test/include/conform_test.h) 中提供了运行时所需 C-API 函数声明,用户根据函数声明实现运行时所需函数,以便测试套件能够在芯片上管理内存等资源。该实现部分仅供测试时使用。
[diopi_test/diopi_stub/include/conform_test.h](../diopi_test/include/conform_test.h) 中提供了运行时所需 C-API 函数声明,用户根据函数声明实现运行时所需函数,以便测试套件能够在芯片上管理内存等资源。该实现部分仅供测试时使用。

<!-- #### 要求实现并注册的函数列表如下
Expand Down Expand Up @@ -54,14 +54,17 @@

#### 实现 DIOPI 函数接口

[proto/include/diopi/functions.h](../proto/include/diopi/functions.h) 根据模型训练和框架开发经验定义了一套标准算子的函数,每一个函数完成一个特定的、需要计算设备参与执行的功能。截止目前,从30个常用模型所需算子的角度出发,定义了所需的常见训练算子。该实现部分会由 TEST 测试后接入训练框架,用于真实模型训练。在实现的过程中,芯片厂商可根据自身特性来优化算子的性能。
[proto/include/diopi/functions.h](../proto/include/diopi/functions.h) 根据模型训练和框架开发经验定义了一套标准算子的函数,每一个函数完成一个特定的、需要计算设备参与执行的功能。截止目前,从30个常用模型所需算子的角度出发,定义了所需的常见训练算子。该实现部分会由 diopi_test 测试后接入训练框架,用于真实模型训练。在实现的过程中,芯片厂商可根据自身特性来优化算子的性能。

另外,PROTO 提供了如张量,标量等基础数据结构,这些基础数据结构也出现在DIOPI标准算子的参数列表中。而其中一些数据接口如张量 *Tensor*,上下文 *Context* 是不透明数据类型 ***Opaque data type***。 因此 [proto/include/diopi/diopirt.h](../proto/include/diopi/diopirt.h) 提供了一套接口用以获取 *Tensor* 的相关信息或者从上下文 *Context* 请求资源。这套接口设计旨在连接训练框架和 DIOPI 算子库, 由训练框架提供给 DIOPI 算子库。而 TEST 将以仅为测试服务的原则实现这套接口。
另外,proto 提供了如张量,标量等基础数据结构,这些基础数据结构也出现在DIOPI标准算子的参数列表中。而其中一些数据接口如张量 *Tensor*,上下文 *Context* 是不透明数据类型 ***Opaque data type***。 因此 [proto/include/diopi/diopirt.h](../proto/include/diopi/diopirt.h) 提供了一套接口用以获取 *Tensor* 的相关信息或者从上下文 *Context* 请求资源。这套接口设计旨在连接训练框架和 DIOPI 算子库, 由训练框架提供给 DIOPI 算子库。而 diopi_test 将以仅为测试服务的原则实现这套接口。

#### 配置 DIOPI 转换逻辑(可选)

`impl/${DEVICE}`下存在文件`convert_config.yaml`时,DIOPI自动转换功能(adaptor)将会开启。
此功能默认会把diopi中的非连续tensor转为连续tensor后,再去调用`impl/${DEVICE}`下的算子。
对与elementwise类算子,可能不需要转为连续,此时可layout可设置为ND. 如不需要adaptor转为功能,则删除`impl/${DEVICE}`下的`convert_config.yaml`.

如果某些算子支持的类型或者layout有限制,可以通过编写配置文件实现调用接口前后的自动转换,转换依赖两个DIOPI接口`diopiDtypeCast``diopiCopyInp``diopiContiguous`因此必须实现这两个接口。需要注意的是,由于这种转换是通过copy来完成的,所以会有一定的性能损耗。
如果某些算子支持的数据类型(dtype)或者数据格式(layout)有限制,例如仅支持某些数据类型或数据格式,可以通过编写配置文件实现调用接口前后的自动转换,从而对数据类型或数据格式进行转换。转换依赖3个DIOPI接口`diopiDtypeCast``diopiCopyInp``diopiContiguous`因此必须实现这3个接口。需要注意的是,由于这种转换是通过copy来完成的,所以会有一定的性能损耗。
此功能的代码逻辑在[adaptor](../adaptor)中,并且在diopi函数接口实现时,需要满足一下条件:

* 所有包含的diopi函数实现的cpp文件需要放在`impl/${DEVICE}/functions/`目录下 <sup>*</sup>
Expand All @@ -70,40 +73,44 @@

[*] 其中${DEVICE}为编译adaptor时,指定的厂商名。

在impl/设备文件夹下新建`convert_config.yaml`文件,配置内容参考:

每个厂商的设备(device)有自己对应的转换规则,具体位于`impl/${DEVICE}/convert_config.yaml`文件,配置内容参考:

```
- common_config:
dtype: (int64)->int32, (float64)->float32
layout: NHWC
layout: NCHW
- diopiAdd:
dtype: (int64)->int32, (float64)->float32
tensor_dtype:
input:(float64)->float32
other:(float64,int64)->float32
out: (float64,int64)->float32
layout: NCHW,NHWC, input(NHWC)
layout: NHWC
```

配置应用可分为三级:
每个设备通用的配置(`common_config`),说明了不支持的dtype以及转换规则、接收的layout(默认为NHWC、NCHW),该配置作用于所有算子
每个算子可以有自己的配置(`diopiAdd`),所有输入输出参数,其中缺省的部分沿用通用配置。
每个参数也可以有自己的配置(`tensor_dtype`):对于特殊的参数可以配置参数粒度的,此时会覆盖算子粒度的配置。
1. 全局的、特定设备通用的配置(`common_config`),该配置作用于所有缺省配置的算子,用于对dtype和layout进行转换
2. 算子粒度的配置(`diopiAdd`),该配置会覆盖通用配置,作用于该算子的所有输入和输出参数,其中缺省的部分沿用通用配置。
3. 参数粒度配置(`tensor_dtype`):对于算子特殊的参数可以配置参数粒度的转换规则,此时会覆盖算子粒度的配置。

##### **配置项说明**

1. **dtype**

可在设备通用配置和算子配置中设置支持的`dtype`,通用配置的选项包括:int8、uint8、int16、uint16、int32、uint32、int64、uint64、float16、float32、float64、bool,算子内各参数可配置的类型为该参数支持的所有类型
可在设备通用配置和算子配置中设置支持的`dtype`,通用配置的选项包括:int8、uint8、int16、uint16、int32、uint32、int64、uint64、float16、float32、float64、bool、complex32、complex64和complex128(具体可以参考adaptor/codegen/gen.py中的str_to_diopi_dtype)字典。算子内各参数可配置的类型为该参数理想情况下支持的所有类型,但如果由于设备硬件或软件栈的限制,导致某些数据类型不支持,则需要将某些的不支持类型转换为支持的类型进行计算
```
# 该算子不支持int64和float64的参数,需要分别转换为int32和float32进行计算,并会在计算完成后转换回原本类型
dtype: (int64)->int32, (float64)->float32
```
括号中为不支持的类型,`->`指向转换后的类型,括号中可以有多个类型,表示这些类型都会转换至`->`后的类型。转换规则可不配置,默认 `dtype: int64->int32`
括号中为不支持的类型,`->`指向转换后的类型,括号中可以有多个类型,表示这些类型都会转换至`->`后的类型。

2. **layout**

layout可配置的选项包括NHWC和NCHW,后续若有其他layout,DIOPI支持后也可配置。配置中两个可同时包含,表示两种类型都支持,默认值即为都支持,对layout没有特殊要求。layout也可以配置算子和参数粒度的,配置形式如下:
layout可配置的选项包括NCHW、NCL、NCDHW、NLC、NHWC、NDHWC和ND(具体可以参考adaptor/codegen/gen.py中的str_to_diopi_format字典),其中ND表示对tensor不做任何layout相关处理。后续若有其他layout,DIOPI支持后也可配置。配置中两个可同时包含,表示两种类型都支持,默认值即为都支持,对layout没有特殊要求。layout也可以配置算子和参数粒度的,配置形式如下:
```
layout: NCHW,NHWC, input(NHWC)
layout: NCHW,input(NHWC) # 表示除input这个tensor进行NHWC转化外,其余tensor进行NCHW转化。
```

限制:diopi接口的输入参数为执行diopiTensorHandle_t的指针时,表示此参数是希望在diopi实现内部申请空间,故此diopi接口不会做任何adaptor相关逻辑(包含memory_format转化和dtype转化)
10 changes: 5 additions & 5 deletions proto/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@
<img src="../img/deepLink_logo.png">
</div>

# PROTO
# proto

PROTO是标准算子接口的原型声明,是芯片厂商实现与框架算子调用的中间层。通过规定标准的运行时函数与算子接口的声明,对框架来说,统一了算子接口,无需考虑芯片厂商具体的算子实现;对厂商来说,可以只聚焦于算子实现与优化,无需考虑框架适配。PROTO作为DIOPI中具体算子声明的环节,起到了承上(框架)启下(芯片厂商)的作用。
DIOPI中的proto是标准算子接口的原型声明,是芯片厂商实现与框架算子调用的中间层。通过规定标准的运行时函数与算子接口的声明,对框架来说,统一了算子接口,无需考虑芯片厂商具体的算子实现;对厂商来说,可以只聚焦于算子实现与优化,无需考虑框架适配。proto组件作为DIOPI中具体算子声明的环节,起到了承上(框架)启下(芯片厂商)的作用。

DIOPI_PROTO有如下核心功能
proto组件有如下核心功能
1. **实现Runtime标准接口定义**
声明了在实现标准算子函数时可以使用的工具函数以及相关数据结构。其中,工具函数用于对Context和Tensor两类对象进行操作。
2. **实现标准算子的接口定义**
声明了标准算子的函数,每一个函数完成一个特定的、需要计算设备参与执行的功能。


PROTO的主要组成部分包括 _运行时函数(diopirt)_ 和 _算子声明(functions)_。运行时函数主要为芯片厂商提供实现算子函数时需要框架提供的工具函数,主要包括一些公共类型的声明以及分配与管理张量数据等;算子声明包含了用于人工智能计算的大量函数声明,为各个算子接口的具体参数及其类型提供了标准化的定义;C-API文档生成为算子声明生成API说明文档,供算子开发与使用者查阅
proto的主要组成部分包括 _运行时函数(diopirt)_ 和 _算子声明(functions)_。运行时函数主要为芯片厂商提供实现算子函数时需要框架提供的工具函数,主要包括一些公共类型的声明以及分配与管理张量数据等;算子声明包含了用于人工智能计算的大量函数声明,为各个算子接口的具体参数及其类型提供了标准化的定义;C-API文档生成为算子声明生成API说明文档,供算子开发与使用者查阅

### 运行时函数(diopirt)
芯片厂商实现的算子函数时,计算过程中可能需要使用设备内存管理、流管理等runtime功能,这些都对设备资源的管理操作需要框架提供相关的函数实现。在PROTO中声明标准的运行时函数抽象,在算子函数运算需要分配内存或要在指定Stream上运行时,即可调用相关函数。
芯片厂商实现的算子函数时,计算过程中可能需要使用设备内存管理、流管理等runtime功能,这些都对设备资源的管理操作需要框架提供相关的函数实现。在proto中声明标准的运行时函数抽象,在算子函数运算需要分配内存或要在指定Stream上运行时,即可调用相关函数。
声明的内容主要包括以下部分:
- 错误码```diopiError_t```、数据类型 ```diopiDtype_t``````diopiSize_t``` 以及不透明数据结构 ```diopiContextHandle_t``````diopiTensorHandle_t```
- 用于对 Tensor 对象进行操作的函数, 包括获取Tensor对象的内存、形状、类型等
Expand Down

0 comments on commit 2e38394

Please sign in to comment.