昇腾社区首页
中文
注册

Tiling下沉

在静态图模式下,可以通过整图下沉优化调度性能。将完整的计算图一次性下发至Device侧,后续执行则无需Host参与,由Device自主完成计算,从而减少Host-Device交互开销,提升执行效率。部分算子的Tiling计算依赖运行时输入的具体数值(Tiling值依赖),需在执行时动态计算Tiling参数。针对该场景,可采用Tiling下沉优化方案:将Tiling计算下沉至Device侧的AI CPU上执行,从而实现计算全程在Device侧高效完成。

  • 基于新版本CANN包(支持Tiling下沉特性)编译生成的Tiling下沉算子,不兼容旧版CANN(不支持Tiling下沉特性)运行环境。
  • 当前仅融合算子(矢量计算和矩阵计算融合)支持进行Tiling下沉。
  • Tiling下沉功能仅支持如下产品型号:
    • Atlas A2 训练系列产品/Atlas 800I A2 推理产品/A200I A2 Box 异构组件
    • Atlas A3 训练系列产品/Atlas A3 推理系列产品

Tiling下沉场景下,算子工程的op_host目录结构如下,将Tiling实现文件单独放在在一个cpp文件中,示例中为add_custom_tiling.cpp。

1
2
3
4
5
├── op_host
   ├── add_custom.cpp // 算子原型定义、InferShape、InferDataType实现
   ├── add_custom_tiling.cpp // Tiling函数实现
   ├── add_custom_tiling.h // TilingData结构体定义、Tiling函数声明
   └── CMakeLists.txt

以AddCustom算子为例,讲解关键代码文件的具体实现方法如下:

  • TilingData结构体定义、Tiling函数声明头文件add_custom_tiling.h
    • 进行TilingData结构体的定义
    • 进行Tiling实现函数的声明
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    #ifndef ADD_CUSTOM_TILING_H
    #define ADD_CUSTOM_TILING_H
    #include "register/tilingdata_base.h"
    #include "register/op_def_registry.h"
    namespace optiling {
    BEGIN_TILING_DATA_DEF(TilingData)
    TILING_DATA_FIELD_DEF(uint32_t, totalLength);
    TILING_DATA_FIELD_DEF(uint32_t, tileNum);
    END_TILING_DATA_DEF;
    REGISTER_TILING_DATA_CLASS(AddCustom, TilingData) // Tiling结构体定义
    } // namespace optiling
    namespace optiling {
      ge::graphStatus TilingFunc(gert::TilingContext* context); // Tiling函数声明
    }
    #endif // ADD_CUSTOM_TILING_H
    
  • Tiling函数的实现文件add_custom_tiling.cpp
    • Tiling实现中,可以获取tensor数据。
    • 完成下沉Tiling函数注册:包含device_op_impl_registry.h头文件,使用宏DEVICE_IMPL_OP_OPTILING进行注册。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    #include "register/device_op_impl_registry.h" // 包含头文件
    #include "add_custom_tiling.h"
    namespace optiling {
    const uint32_t BLOCK_DIM = 8;
    const uint32_t TILE_NUM = 8;
    ge::graphStatus TilingFunc(gert::TilingContext *context)
    {
        TilingData tiling;
        uint32_t totalLength = context->GetInputShape(0)->GetOriginShape().GetShapeSize();
        context->SetBlockDim(BLOCK_DIM);
        tiling.set_totalLength(totalLength);
        tiling.set_tileNum(TILE_NUM);
        tiling.SaveToBuffer(context->GetRawTilingData()->GetData(), context->GetRawTilingData()->GetCapacity());
        context->GetRawTilingData()->SetDataSize(tiling.GetDataSize());
        // 设置值依赖后,可以通过TilingContext::GetOptionalInputTensor获取到tensor数据
        auto tensor = context->GetOptionalInputTensor(0)->GetData<float>();
        if (tensor != nullptr) {
            printf("tensor[0] = %f \n", tensor[0]);
        }
        context->SetTilingKey(0);
        size_t *currentWorkspace = context->GetWorkspaceSizes(1);
        currentWorkspace[0] = 0;
        return ge::GRAPH_SUCCESS;
    }
    } // namespace optiling
    DEVICE_IMPL_OP_OPTILING(AddCustom).Tiling(optiling::TilingFunc); // 将Tiling函数以及其OpType注册到Tiling下沉
    
  • 算子原型定义、InferShape、InferDataType实现文件add_custom.cpp,需包含add_custom_tiling.h,进行Tiling函数和算子原型定义的关联。
    Tiling下沉仅适用于存在Tiling值依赖(即当InferShape不依赖输入值,仅Tiling计算需要输入值)且算子输入为非Const类型的场景,本示例中的输入x通过ValueDpend配置了非Const类型的Tiling值依赖。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #include "add_custom_tiling.h" // 包含头文件
    // ...
    namespace ops {
    class AddCustom : public OpDef {
    public:
        AddCustom(const char* name) : OpDef(name)
        {
            this->Input("x")
                .ParamType(REQUIRED)
                .DataType({ge::DT_FLOAT})
                .Format({ge::FORMAT_ND})
                .ValueDepend(OPTIONAL, DependScope::TILING); // 表示输入x为Tiling值依赖
            this->Input("y")
                .ParamType(REQUIRED)
                .DataType({ge::DT_FLOAT})
                .Format({ge::FORMAT_ND});
            this->Output("z")
                .ParamType(REQUIRED)
                .DataType({ge::DT_FLOAT})
                .Format({ge::FORMAT_ND});
            // 如下的shape/datatype推导函数仅在算子入图场景使用
            this->SetInferShape(ge::InferShape);
            this->SetInferDataType(ge::InferDataType);  
            this->AICore()
                .SetTiling(optiling::TilingFunc); // Tiling函数和算子原型定义的关联
            // 请替换为实际的昇腾AI处理器型号
            this->AICore().AddConfig("ascendxxx");
        }
    };
    OP_ADD(AddCustom);
    } // namespace ops
    
  • 修改编译脚本CMakeLists.txt,添加Tiling下沉编译命令。具体代码如下所示:
    1
    2
    3
    4
    # 通过ascendc_device_library添加Tiling下沉编译任务
    ascendc_device_library( TARGET cust_opmaster # 任务名称,固定为cust_opmaster
                            OPTION SHARED # 动态库(当前仅支持动态库入图下沉)
                            SRC ${CMAKE_CURRENT_SOURCE_DIR}/add_custom_tiling.cpp ) # Tiling函数实现代码源文件