AKG 学习
学习AKG的算子编译流程, 主要关于后端.
Example 1
这个例子在m1上无法执行, 因为在codegen中直接加了x86的指令.
❯ pytest -s tests/st/ops/test_batch_matmul.py -m "platform_x86_cpu"
tests/common/test_run/batch_matmul_run.py
中的batch_matmul_run
执行核心测试逻辑.
- 通过te构建batch matmul的op, 以及得到输入输出的Expr.
- 调用c++部分的
third_party/incubator-tvm/include/tvm/schedule.h:create_schedule
返回得到当前op的schedule - 回到python中将schedule与op var等交给c++部分进行function build
src/codegen/build_module.cc:BuildToFunc
BuildToFunc
- 执行提前注册好的llvm的lower
src/codegen/lower_llvm.cc:LLVMLowerImpl
对schedule的结果进行lower, 同时每个stage的逻辑都在这个文件中被注册:
REG_STAGE_LOWER("llvm", StageType::Begin, "BEGIN", LLVMLowerBegin);
REG_STAGE_LOWER("llvm", StageType::Tuning, "TUNING", LLVMLowerStageTuning);
REG_STAGE_LOWER("llvm", StageType::Poly, "POLY", LLVMLowerPoly);
REG_STAGE_LOWER("llvm", StageType::BeforeFlattern, "BEFORE_FLATTERN", LLVMLowerBeforeFlattern);
REG_STAGE_LOWER("llvm", StageType::Flattern, "FLATTERN", LLVMLowerFlattern);
REG_STAGE_LOWER("llvm", StageType::BeforeLowerFunc, "BeforeLowerFunc", LLVMBeforeLowerFunc);
REG_STAGE_LOWER("llvm", StageType::End, "END", LLVMLowerDone);
- 在lower中通过StageManager获取所有需要lower的stage: [Begin,Tuning,Poly,BeforeFlattern,Flattern,BeforeLowerFunc,End],然后依次执行.
Begin Stage
对应src/codegen/lower_llvm.cc:LLVMLowerBegin
.
在LLVMLowerBegin
中需要执行一些基础的pass/analysis来为后续的lower
pass提供信息. LowerInitWithSchedule -> GetBinds
note right
将所有原始schedule中的tensor构造出对应的buffer并存放到`data->arg_list_0`和`data->binds_0`中.
注意`LowerData`中有着如下代码, 让人无法了解具体的含义.
```cpp
Array<NodeRef> args;
Array<NodeRef> arg_list_0;
Map<Tensor, Buffer> binds;
Map<Tensor, Buffer> binds_0;
1. LowerInitWithSchedule
- GetBinds
- AutoInline 应该是inline一些op, 具体实现没有细看, 里面有许多需要特判的case.
- AutoFuse 应该是将多层的op自动fuse起来, 后续具体的fuse逻辑比较复杂.
```cpp
bool NeedToFuse() {
if (HasExternOp()) { // 如果包含ExternOp那么不fuse
return false;
}
// ReduceCheck 检查内部的reduce最大有没有超过shared memory的大小. (同时目前的代码是有matmul就不fuse,可能有什么限制.)
if (ReduceCheck() || !split_config_.empty()) { // 当然如果强行指定了split config那么也能fuse
return true;
}
return false;
}
- 调用tvm自带的
InferBound
和ScheduleOps
进行操作 - TensorAccessRewrite
这个应该是消除显式的
tensor load/store
.
- ReplaceSeparator 将所有的名字中的
.
替换成_
, 可能是为了方便调用isl
. - RewriteMultiValueFunc
- RenameRealize
- ElementwiseFlatten
- FuseAxisExternOp
- AddAttrForLayoutOp
- RewriteTensorIndex
Tips
卷积的test无法在cpu上执行,不知道为什么在构造Conv的te compute的时候限制了.