Skip to content

Commit

Permalink
Merge pull request #208 from hyperai/feat/docusaurus-3
Browse files Browse the repository at this point in the history
  • Loading branch information
sparanoid authored Nov 1, 2023
2 parents 3de4cf8 + 93422be commit fbc33aa
Show file tree
Hide file tree
Showing 116 changed files with 4,031 additions and 3,179 deletions.
6 changes: 3 additions & 3 deletions docs/arch/arch/05-device_target_interactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ sidebar_position: 150
* [Target](#tvm-target-specific-target) 类描述了运行函数的设备。它既对 target 代码生成器公开,也对优化 pass 公开。
* [target 代码生成器](#tvm-target-specific-codegen) 从 IRModule 构造了一个 [模块](/docs/arch/arch/runtimes#module),它由一个或多个 [PackedFunc](/docs/arch/arch/runtimes#PackedFunc) 组成。

## DeviceAPI {#tvm-target-specific-device-api}
## DeviceAPI

`DeviceAPI` 表示特定硬件设备 API 的句柄。(例如,`CUDADeviceAPI` 通过 CUDA 框架处理所有的交互。)大多数 `DeviceAPI` 方法接收一个 `device_id` 参数,来指定访问哪个设备。Python 中通常用 `tvm.runtime.device()` 函数访问它们,这个函数返回特定设备的句柄,通过特定 API 访问。(例如,`tvm.runtime.device()` 通过 CUDA API 访问物理设备 `0`。)

Expand Down Expand Up @@ -52,7 +52,7 @@ TVM 框架若要使用新的 DeviceAPI,应该按照以下步骤注册:
2.[device_api.h](https://github.com/apache/tvm/blob/main/include/tvm/runtime/device_api.h) 中的 `DeviceName` 添加一个案例,从而将枚举值转换为字符串表示形式。这个字符串表示应该和 `TVM_REGISTER_GLOBAL` 的名称匹配。
3. 将入口添加到 `tvm.runtime.Device``MASK2STR``STR2MASK` 字典,获取新的枚举值。

## Target 定义 {#tvm-target-specific-target}
## Target 定义

`Target` 对象是属性(包含物理设备、其硬件/驱动程序限制,及其功能)的查找表。在优化和代码生成阶段都可以访问 `Target`。虽然相同的 `Target` 类适用于所有 runtime target,但每个 runtime target 可能需要添加特定于 target 的选项。

Expand All @@ -64,7 +64,7 @@ TVM 框架若要使用新的 DeviceAPI,应该按照以下步骤注册:

代码生成器中可以用 C++ 中的 `target->GetAttr<T>(param_name)`,或是 Python 中的 `target.attrs` 字典来访问 target 属性。

## Target 代码生成器 {#tvm-target-specific-codegen}
## Target 代码生成器

代码生成器采用优化的 `IRModule`,并将其转换为可执行表示。每个代码生成器注册后,才能被 TVM 框架使用。这是通过注册 `"target.build.foo"` 函数来完成的,其中 `foo` 与上面的 `TVM_REGISTER_TARGET_KIND` 定义中使用的名称相同。

Expand Down
22 changes: 11 additions & 11 deletions docs/arch/arch/07-inferbound.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ InferBound pass 有两个不是很明显的属性:
消息传递函数被命名为「PassUp」或「PassDown」,取决于消息是从 DAG 中的子代传递给其父代(「PassUp」),还是从父代传递给其子代(「PassDown」)。例如,上图左侧的大箭头显示 PassDownDomain 从根 IterVar `i` 向其子 `i.outer` 和 `i.inner` 发送消息。
## PassDownDomain {#passdowndomain}
## PassDownDomain
PassDownDomain 的作用是为 root_iter_vars 取 InferRootBound 产生的 Range,并设置 stage 中所有其他 IterVars 的 Range。
Expand Down Expand Up @@ -193,7 +193,7 @@ InferBound 调用 InferRootBound,然后在 stage 计算图中的每个 stage

*对于包含 compute_at 的 schedules**而言**,InferBound 更为复杂。因此首先**针对**不包含 compute_at 的 schedules**解读**InferBound。*

### 阶段 1:为 consumer 的 leaf_iter_vars 初始化 IntSet {#phase1}
### 阶段 1:为 consumer 的 leaf_iter_vars 初始化 IntSet

``` c++
/*
Expand All @@ -212,7 +212,7 @@ InferBound 调用 InferRootBound,然后在 stage 计算图中的每个 stage

简单起见,假设 schedule 不包含线程轴。这种情况下,仅当 schedule 包含 compute_at 时,才和案例 2 相关。参阅 [InferBound 与 compute_at](#inferboundca) 节来进一步获取更多信息。

### 阶段 2:将 IntSet 从 consumer 的 leaf 传到 consumer 的 root {#phase2}
### 阶段 2:将 IntSet 从 consumer 的 leaf 传到 consumer 的 root

```c++
/*
Expand Down Expand Up @@ -293,7 +293,7 @@ IntSet 的并集是通过将每个 IntSet 转换为一个区间来计算的,

![图片](/img/docs/tvmai/tvmai.github.io/main/images/docs/inferbound/gatherbound_problem.png)

## InferBound 与 compute_at {#inferboundca}
## InferBound 与 compute_at

若 schedule 包含 compute_at,则 InferRootBound 的阶段 1-2 会变得更加复杂。

Expand Down Expand Up @@ -377,7 +377,7 @@ public:
再次考虑上面的例子。为了让 InferBound 确定必须计算 C 的多少元素,重要的是,要知道 C 的计算是发生在 D 的叶变量的范围内,还是在该范围之上。在例 1 中,C 的计算发生在 D 的所有叶变量的范围*之上*。在例 2,C 的计算发生在 D 的所有叶变量的范围*内*。在例 3,C 出现在D 的 i 维度的范围内,但在 D 的 j 维度的范围之上。
CreateAttachPath 负责确定哪些作用域包含 stage C。这些作用域按从最内层到最外层的顺序排列。因此,对于每个 stage,CreateAttachPath 都会生成一个「附加路径」,其中列出了包含该 stage 从最里面到最外面的范围,在例 1,C 的附加路径为空。在例 2,C 的附加路径包含 {j,i}。在例 3,C 的附加路径是 {i}。
CreateAttachPath 负责确定哪些作用域包含 stage C。这些作用域按从最内层到最外层的顺序排列。因此,对于每个 stage,CreateAttachPath 都会生成一个「附加路径」,其中列出了包含该 stage 从最里面到最外面的范围,在例 1,C 的附加路径为空。在例 2,C 的附加路径包含 `{j,i}`。在例 3,C 的附加路径是 `{i}`
以下示例阐明了附加路径的概念,适用于更复杂的情况。
Expand Down Expand Up @@ -415,11 +415,11 @@ realize D([0, 4], [0, 5], [0, 16]) {
}
```
在这种情况下,C 的附加路径是 {dk, dj, di}。注意 C 没有使用 di,但 di 仍然出现在 C 的附加路径中。
在这种情况下,C 的附加路径是 `{dk, dj, di}`。注意 C 没有使用 di,但 di 仍然出现在 C 的附加路径中。
**例 5**
根据上述定义,可以很自然地在拆分后应用 Compute_at。下面例子中,C 的附着点是 D 的 j_inner。C 的附着路径是 {j_inner, j_outer, i}。
根据上述定义,可以很自然地在拆分后应用 Compute_at。下面例子中,C 的附着点是 D 的 j_inner。C 的附着路径是 `{j_inner, j_outer, i}`
``` python
C = tvm.compute((5, 16), lambda i, j : tvm.const(5, "int32"), name='C')
Expand Down Expand Up @@ -456,7 +456,7 @@ s[C].compute_at(s[D], D.op.axis[1])
s[D].compute_at(s[E], E.op.axis[1])
```

`debug_keep_trivial_loop=True` 时,C 的附加路径为 {dj,di,ej,ei},D 的附加路径为 {ej,ei}:
`debug_keep_trivial_loop=True` 时,C 的附加路径为 `{dj,di,ej,ei}`,D 的附加路径为 `{ej,ei}`

``` c++
// attr [D] storage_scope = "global"
Expand Down Expand Up @@ -494,7 +494,7 @@ produce E {

若没有附加,则已经为 consumer 变量计算的 Range 定义了 consumer 需要多少 C。但是,若 stage 实际上在 consumer 变量 j 的一个范围内,那么一次只需要 j 的范围内的一个点。

### 阶段 1:为 consumer 的 leaf_iter_vars 初始化 IntSet {#phase1ca}
### 阶段 1:为 consumer 的 leaf_iter_vars 初始化 IntSet

``` c++
/*
Expand All @@ -512,7 +512,7 @@ produce E {
* 案例 3:需要释放。这种情况下,leaf 的 Range 被简单地转换为 IntSet。
若在 consumer 中遇到 stage C 的附着点,就会发生案例 2。对于此 attach_ivar,以及 consumer 的所有更高叶变量,将应用案例 2。若 C 在叶变量的 Range 内,这将确保仅请求叶变量范围内的单个点。

### 阶段 2:将 IntSet 从 consumer 的 leaf 传到 consumer 的 root {#phase2ca}
### 阶段 2:将 IntSet 从 consumer 的 leaf 传到 consumer 的 root

``` c++
/*
Expand All @@ -530,7 +530,7 @@ produce E {

PassUpDomain 将 up_state 向 consumer 传给所有 IterVars 后,将创建一个从 root_iter_vars 到 IntSet 的新映射。若 stage 没有附加到当前 consumer,那么对于 consumer 的 attach_path 中的每个变量 iv,将 iv 的 Range 添加到一个 `relax_set`。stage 的 root 变量是根据这个 `relax_set` 进行评估的。

这是为了处理类似以下示例的情况,其中 C 没有附加到任何地方,但它的 consumer D 在 stage E 中附加。这种情况下,在确定 C 有多少需要计算时,必须考虑 D 的 attach_path,{ej,ei}。
这是为了处理类似以下示例的情况,其中 C 没有附加到任何地方,但它的 consumer D 在 stage E 中附加。这种情况下,在确定 C 有多少需要计算时,必须考虑 D 的 attach_path,`{ej,ei}`

``` python
C = tvm.compute((5, 16), lambda ci, cj : tvm.const(5, "int32"), name='C')
Expand Down
2 changes: 1 addition & 1 deletion docs/arch/arch/10-relay_op_strategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def conv2d_strategy_mytarget(attrs, inputs, out_type, target):
...
```

## 从 Op 策略中选择实现 {#select-implementation-from-op-strategy}
## 从 Op 策略中选择实现

在编译过程中,Relay 编译引擎要确定当有多个算子时,使用哪个算子来实现。选择策略的工作原理如下。

Expand Down
2 changes: 1 addition & 1 deletion docs/arch/arch/11-convert_layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ ConvertLayout pass 非常易于使用。pass 不是默认 relay.build pipeline

为了指定要转换到的布局,创建一个映射,该映射由重度布局敏感的算子指向该算子期望布局的列表。以下第一个示例指定了数据布局,允许内核布局自动转换为 TVM 支持的布局(针对特定的数据布局和算子)。这是通过使用「default」关键字指定的。

第二个示例显示了如何转换为指定内核布局。注意,以下示例将转换为相同的布局,即 {‘nn.conv2d’: [‘NCHW’, ‘default’]} == {‘nn.conv2d’: [‘NCHW’, ‘OIHW’]}
第二个示例显示了如何转换为指定内核布局。注意,以下示例将转换为相同的布局,即 `{‘nn.conv2d’: [‘NCHW’, ‘default’]} == {‘nn.conv2d’: [‘NCHW’, ‘OIHW’]}`

``` python
# TFlite 框架到 Relay 解析器 - 默认布局是 NHWC
Expand Down
24 changes: 12 additions & 12 deletions docs/arch/arch/12-benchmark.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ sidebar_position: 220
| runtime_ms_std | 5.3 | statistics | |
| timestamp | 1572282699.6 | metadata | indicates when this record is logged |
| schema_version | “0.1” | metadata | ensure reproducibility as we iterate on this schema |
| metadata | { “docker_tag”:”gcr.io/…/0a680”, … } | metadata | docker_tag is optional |
| workload_args | {“input_name”: “Input3”, “input_shape”: [list_of_shape], “data_layout”: NHCW} | workload | |
| workload_metadata | {“class”: “vision”,”doc_url”: “https://github.com/.../README.md”, “opset”: 7,”type”: “body_analysis”,”url”: “https://onnxzoo...ferplus.tar.gz”, “md5”: “07fc7…”} | workload | source of workload |
| metadata | `{ “docker_tag”:”gcr.io/…/0a680”, … }` | metadata | docker_tag is optional |
| workload_args | `{“input_name”: “Input3”, “input_shape”: [list_of_shape], “data_layout”: NHCW}` | workload | |
| workload_metadata | `{“class”: “vision”,”doc_url”: “https://github.com/.../README.md”, “opset”: 7,”type”: “body_analysis”,”url”: “https://onnxzoo...ferplus.tar.gz”, “md5”: “07fc7…”}` | workload | source of workload |
| engine_version | “1.0.5” | compiler | use semvar format |
| engine_config | {“llvm”: “llvm-8”, “nvcc”: 10.1, “accelerator”: “MLAS”, “relay_opt_level”: 3, “tvm_target”:”llvm -mcpu=cascadelake”} | compiler | fields are optionally specified |
| compilation_config | {“opt_level”: 3, “layer_schedules”:[]/ <SHA_to_schedules>} | compiler | fields are optionally specified |
| software_config | {“os”: “ubuntu:18.04”,”pip”: { “docker”: “4.1.0”, “gitpython”: “3.0.4”, “numpy”: “1.17.4”, “onnx”: “1.6.0”}, “cudnn”: “cudnn-8”, “cuda_driver”: “480.10.1”} | backend | env dependency list |
| runtime_config | {“num_cpu_threads”: 3} | backend | info on non-hardware, non-software metadata |
| hardware_config | {“cpu_count”: 16, “cloud_machine_type”:”c2-standard-16”, “memory_GB”:64} | hardware | json descriptor of target hardware environment |
| execution_config | {“number”: 1, “repeat”: 10, “min_repeat_ms”, 0} | statistics | workload execution parameters |
| metrics | {“accuracy”: 48.5,“compilation_ms_mean”: 12} | statistics | other metrics |
| runtime_raw | [{“runtime_ms”: 12, …}, {“runtime_ms”:13,…},…] | statistics | optional raw metrics array |
| engine_config | `{“llvm”: “llvm-8”, “nvcc”: 10.1, “accelerator”: “MLAS”, “relay_opt_level”: 3, “tvm_target”:”llvm -mcpu=cascadelake”}` | compiler | fields are optionally specified |
| compilation_config | `{“opt_level”: 3, “layer_schedules”:[]/ <SHA_to_schedules>}` | compiler | fields are optionally specified |
| software_config | `{“os”: “ubuntu:18.04”,”pip”: { “docker”: “4.1.0”, “gitpython”: “3.0.4”, “numpy”: “1.17.4”, “onnx”: “1.6.0”}, “cudnn”: “cudnn-8”, “cuda_driver”: “480.10.1”}` | backend | env dependency list |
| runtime_config | `{“num_cpu_threads”: 3}` | backend | info on non-hardware, non-software metadata |
| hardware_config | `{“cpu_count”: 16, “cloud_machine_type”:”c2-standard-16”, “memory_GB”:64}` | hardware | json descriptor of target hardware environment |
| execution_config | `{“number”: 1, “repeat”: 10, “min_repeat_ms”, 0}` | statistics | workload execution parameters |
| metrics | `{“accuracy”: 48.5,“compilation_ms_mean”: 12}` | statistics | other metrics |
| runtime_raw | `[{“runtime_ms”: 12, …}, {“runtime_ms”:13,…},…]` | statistics | optional raw metrics array |

## 存储格式

Expand Down Expand Up @@ -98,4 +98,4 @@ sidebar_position: 220
"execution_config":{},
"metrics":{}
}
```
```
2 changes: 1 addition & 1 deletion docs/arch/arch/17-model_library_format.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ TVM 生成的所有代码都放在这个目录中。编写代码时,生成的
* `target`:将 `device_type`(潜在的整数,作为字符串)映射到描述用于该 `device_type` 的 Relay 后端的子 target 的字典。
* `version`:标识模型库格式中格式的数字版本号。当元数据结构或磁盘结构更改时,这个数字会增加。本文档反映的是第 `5` 版。

### 内存使用总结 {#memory-usage-summary}
### 内存使用总结

它是具有如下子键的字典:

Expand Down
6 changes: 3 additions & 3 deletions docs/arch/arch/runtimes/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ TVM 支持多种编程语言进行编译器堆栈开发和部署。本文档将
* 实验:将编译好的函数发送到嵌入式设备上直接运行。
我们期望能够用任何语言定义一个函数,然后用另一种语言调用。还期望将 runtime 内核最小化,部署到嵌入式设备。

## PackedFunc {#PackedFunc}
## PackedFunc

[PackedFunc](https://github.com/apache/tvm/blob/main/include/tvm/runtime/packed_func.h) 是一个简单而优雅的解决方案,它可以解决以上问题。单个 `PackedFunc` 对象代表一个函数调用,其调用者和被调用者可能使用不同的语言。

Expand Down Expand Up @@ -104,7 +104,7 @@ PackedFunc 用于编译器和部署堆栈:

与普通函数相比,调用 PackedFunc 的开销很小,因为它只在堆栈上保存了几个值,所以只要不包装小的函数即可。总之,PackedFunc 是 TVM 中的通用粘合剂,可以广泛使用它来支持编译器和部署。

## 模块 {#module}
## 模块

由于 TVM 支持多种类型的设备,因此需要支持不同类型的驱动程序。必须用驱动程序 API 来加载内核,以打包格式设置参数,并执行内核启动。

Expand Down Expand Up @@ -209,6 +209,6 @@ PackedFunc 中的每个参数都包含一个关联值 [TVMValue](https://github.
* [c_runtime_api.cc](https://github.com/apache/tvm/blob/main/src/runtime/c_runtime_api.cc#L262),用于 C API 以及如何提供回调。
为了支持扩展类型,使用了注册表系统来注册类型相关信息,如 C++ 中对所有类型的支持,参阅 [扩展类型](https://github.com/apache/tvm/tree/main/apps/extension) 了解更多详细信息。

# Runtime 特定信息 {#runtime-specific-information}
# Runtime 特定信息

* [Vulkan Runtime](vulkan)
2 changes: 1 addition & 1 deletion docs/arch/arch/runtimes/vulkan.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ TVM 支持用 Vulkan 计算着色器(Vulkan compute shaders)来查询。所

截至 2021 年 5 月,还有一些 Vulkan 的实现没支持。例如,要支持 64 位整数。若不支持 Vulkan target,则会在 SPIR-V 代码生成期间报错。我们正努力消除这些限制,并支持其他 Vulkan 实现。

## SPIR-V 功能 {#tvm-table-vulkan-capabilities}
## SPIR-V 功能

某些特定于设备的功能还对应于 SPIR-V 功能或扩展,它们必须在着色器中声明,或对应于要使用某个功能所需的最低 SPIR-V 版本。TVM 生成的着色器将声明执行编译好的计算图所需的最小扩展/功能集,以及 SPIR-V 的最小允许版本。

Expand Down
4 changes: 2 additions & 2 deletions docs/arch/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ title: 设计与架构

本指南提供了架构的一些补充视图。首先研究端到端的编译流程,并讨论关键的数据结构和转换。这种基于 runtime 的视图侧重于运行编译器时每个组件的交互。接下来研究代码库的逻辑模块及其关系。这部分提供了设计的静态总体视图。

## 编译流程示例 {#example-compilation-flow}
## 编译流程示例

本指南研究编译器中的编译流程示例,下图显示了流程。在高层次,它包含以下步骤:

Expand Down Expand Up @@ -132,7 +132,7 @@ result = gmod["get_output"](0).numpy()
* 编写一组自定义转换(例如自定义量化)。
* 用 TVM 的 Python API 直接操作 IR。

## 逻辑架构组件 {#logical-architecture-components}
## 逻辑架构组件

![/img/docs/tlc-pack/web-data/main/images/design/tvm_static_overview.svg](/img/docs/tlc-pack/web-data/main/images/design/tvm_static_overview.svg)

Expand Down
14 changes: 7 additions & 7 deletions docs/contribute/code_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,26 @@ python tests/scripts/ci.py lint
clang-format 并不完美,必要时可以在某些代码区域上禁用 clang-format。

``` c++
// clang-format off
void Test() {
// clang-format off
void Test() {
// clang-format 将在这个区域禁用。
}
}
// clang-format on
```

因为 clang-format 可能无法识别宏,所以建议像普通函数样式一样使用宏。

``` c++
#define MACRO_IMPL { custom impl; }
#define MACRO_IMPL { custom impl; }
#define MACRO_FUNC(x)

// 不是首选,因为 clang-format 可能会将其识别为类型。

// 首选
// 首选
virtual void Func2() MACRO_IMPL;

void Func3() {
// 首选
// 首选
MACRO_FUNC(xyz);
}
```
Expand All @@ -68,7 +68,7 @@ def test_mytest(target, dev):
...
```

`target="llvm"``target="cuda"` 和其他几个运行 `test_mytest`。这可以确保测试由 CI 在正确的硬件上运行。如果只想针对几个 target 进行测试,请使用 `@tvm.testing.parametrize_targets("target_1", "target_2")`。如果想在单个 target 上进行测试,请使用来自 `tvm.testing()`{.interpreted-text role="func"} 的相关装饰器。例如,CUDA 测试使用 `@tvm.testing.requires_cuda` 装饰器。
`target="llvm"``target="cuda"` 和其他几个运行 `test_mytest`。这可以确保测试由 CI 在正确的硬件上运行。如果只想针对几个 target 进行测试,请使用 `@tvm.testing.parametrize_targets("target_1", "target_2")`。如果想在单个 target 上进行测试,请使用来自 `tvm.testing()` 的相关装饰器。例如,CUDA 测试使用 `@tvm.testing.requires_cuda` 装饰器。

## 处理整型常量表达式

Expand Down
Loading

0 comments on commit fbc33aa

Please sign in to comment.