CANN学习资源开源仓的算子贡献开发二UT和ST测试

举报
黄生 发表于 2026/03/30 20:01:28 2026/03/30
【摘要】 无需编译部署算子包,通过UT(单元测试)方式验证Infershape推导结果、Tiling实现逻辑、Kernel实现逻辑是否符合预期。UT目录结构需手工创建。Tiling UT文件 tests/ut/op_host/test_add_custom_tiling.cpp#include <iostream>#include <gtest/gtest.h>#include "tiling_con...

无需编译部署算子包,通过UT(单元测试)方式验证Infershape推导结果、Tiling实现逻辑、Kernel实现逻辑是否符合预期。UT目录结构需手工创建。Tiling UT文件 tests/ut/op_host/test_add_custom_tiling.cpp

#include <iostream>
#include <gtest/gtest.h>
#include "tiling_context_faker.h"
#include "tiling_case_executor.h"

//测试类、继承Test类,实现SetUpTestCase和TearDownTestCase静态方法
class AddCustomTilingTest : public testing::Test {
protected:
    static void SetUpTestCase()
    {
        std::cout << "AddCustomTilingTest SetUp" << std::endl;
    }

    static void TearDownTestCase()
    {
        std::cout << "AddCustomTilingTest TearDown" << std::endl;
    }
};

//定义至少一个测试用例,通常使用TEST_F宏定义
TEST_F(AddCustomTilingTest, add_custom_tiling_test_1)
{
    struct AddCustomCompileInfo {
    } compileInfo;
    gert::TilingContextPara tilingContextPara(
        "AddCustom",
        {
            {{{8, 2048}, {8, 2048}}, ge::DT_FLOAT, ge::FORMAT_ND},
            {{{8, 2048}, {8, 2048}}, ge::DT_FLOAT, ge::FORMAT_ND},
        },
        {
            {{{8, 2048}, {8, 2048}}, ge::DT_FLOAT, ge::FORMAT_ND},
        },
        {
            /* attrs */
        },
        &compileInfo, // 编译信息,不需要传递时可以为空结构体或nullptr
        64, // 设置可用核数, tiling实现内获取硬件产品信息核数时会获取该值
        262144 // 设置可用UB大小, tiling实现内获取硬件产品信息UB大小时会获取该值
          // 设置tilingdata大小,该参数可不填
        ); 
    //设定预期结果
    uint64_t expectTilingKey = 0;
    string expectTilingData = "16384 1 "; //"tiling结构体第一个字段预期值 tiling结构体第二个字段预期值......"
    std::vector<size_t> expectWorkspaces = {0};
    ExecuteTestCase(tilingContextPara, ge::GRAPH_SUCCESS, expectTilingKey, expectTilingData, expectWorkspaces);
}

执行测试:

# 清理之前测试生成文件
rm -rf build build_out
# 执行测试
cd Sources/ops-math;bash build.sh -u --ophost --ops=add_custom --experimental

输出:

[2026-03-30 18:17:04] [----------] 1 test from AddCustomTilingTest
[2026-03-30 18:17:04] AddCustomTilingTest SetUp
[2026-03-30 18:17:04] [ RUN      ] AddCustomTilingTest.add_custom_tiling_test_1
[2026-03-30 18:17:04] [INFO] GE(9355,math_op_host_ut):2026-03-30-18:17:04.039.079 [op_context_builder_impl.cc:103]9355 CreateComputeNodeInfoImpl:Node AddCustom, compute_node_info attr_size 48, outputs_ins_info_size:48, offset:608, total_size:712.
[2026-03-30 18:17:04] [       OK ] AddCustomTilingTest.add_custom_tiling_test_1 (1 ms)
[2026-03-30 18:17:04] AddCustomTilingTest TearDown
[2026-03-30 18:17:04] [----------] 1 test from AddCustomTilingTest (1 ms total)
[2026-03-30 18:17:04] 
[2026-03-30 18:17:04] [----------] Global test environment tear-down
[2026-03-30 18:17:04] Global Environment TearDown
[2026-03-30 18:17:04] [==========] 1 test from 1 test suite ran. (16 ms total)
[2026-03-30 18:17:04] [  PASSED  ] 1 test.

Kernel UT文件 tests/ut/op_kernel/test_add_custom.cpp

#include <gtest/gtest.h>
#include "tikicpulib.h"
#include "data_utils.h"
#include "../../../op_kernel/add_custom.cpp"
class AddCustomKernelTest : public testing::Test {
protected:
    //数据准备与清理工作(如拷贝数据目录、chmod、生成bin)
    static void SetUpTestCase()
    {
        std::cout << "AddCustomKernelTest SetUp\n" << std::endl;
        const std::string cmd = "cp -rf " + dataPath + " ./";
        system(cmd.c_str());
        system("chmod -R 755 ./add_custom_data/");
    }
    static void TearDownTestCase()
    {
        std::cout << "AddCustomKernelTest TearDown\n" << std::endl;
    }
private:
    const static std::string rootPath;
    const static std::string dataPath;
};

// 设置python生成的测试数据和预期结果路径
const std::string AddCustomKernelTest::rootPath = "../../../../";
const std::string AddCustomKernelTest::dataPath = rootPath + "experimental/math/add_custom/tests/ut/op_kernel/add_custom_data";

//定义至少一个测试用例,通过CPU调试核函数来测试kernel实现逻辑是否符合预期,使用TEST_F宏定义
TEST_F(AddCustomKernelTest, test_case_0)
{
    // 1.设定输入shape/format/dtype,必要时准备ValueDepend输入值
    size_t xByteSize = 8 * 2048 * sizeof(float);
    size_t yByteSize = 8 * 2048 * sizeof(float);
    size_t zByteSize = 8 * 2048 * sizeof(float);
    size_t tiling_data_size = sizeof(AddCustomTilingData);
    uint32_t numBlocks = 64;
    
    // 调用python脚本生成测试输入和预期输出
    system("cd ./add_custom_data/ && python3 gen_data.py");
    std::string input1 = "./add_custom_data/input1.bin";
    std::string input2 = "./add_custom_data/input2.bin";

    // 2.申请输入/输出/workspace/tiling内存
    // 读取输入文件作为测试输入
    uint8_t* x = (uint8_t*)AscendC::GmAlloc(xByteSize);
    ReadFile(input1, xByteSize, x, xByteSize);

    uint8_t* y = (uint8_t*)AscendC::GmAlloc(yByteSize);
    ReadFile(input2, yByteSize, y, xByteSize);

    uint8_t* z = (uint8_t*)AscendC::GmAlloc(zByteSize);
    uint8_t* workspace = (uint8_t*)AscendC::GmAlloc(32);
    uint8_t* tiling = (uint8_t*)AscendC::GmAlloc(tiling_data_size);

    char* path_ = get_current_dir_name();
    std::string path(path_);

    // 3. 设置tilingdata数据
    AddCustomTilingData* tilingDatafromBin = reinterpret_cast<AddCustomTilingData*>(tiling);
    tilingDatafromBin->totalLength = 8 * 2048;
    tilingDatafromBin->tileNum = 1;

    // 4. 设置TilingKey和使用核的类型
    ICPU_SET_TILING_KEY(0);
    AscendC::SetKernelMode(KernelMode::AIV_MODE);

    // 调用核函数并传入构造好的输入和tilingdata
    ICPU_RUN_KF(add_custom<0>,
        numBlocks,
        x,
        y,
        z,
        workspace,
        (uint8_t *)(tilingDatafromBin));

    // 指定算子运算结果保存文件
    std::string outFile = "./add_custom_data/output.bin";
    WriteFile(outFile, z, zByteSize);

    // 5. 释放资源
    AscendC::GmFree(x);
    AscendC::GmFree(y);
    AscendC::GmFree(z);
    AscendC::GmFree(workspace);
    AscendC::GmFree(tiling);

    // 6. 执行对比
    system("cd ./add_custom_data/ && python3 compare_data.py");
    free(path_);
}

里面用到的测试数据生成脚本 tests/ut/op_kernel/add_custom_data/gen_data.py、数据对比脚本 tests/ut/op_kernel/add_custom_data/compare.py,略过。

Kernel UT需要增加编译脚本(tests/ut/op_kernel/CMakeLists.txt)

if (UT_TEST_ALL OR OP_KERNEL_UT)
    # 需要将Tiling依赖的文件添加到CMakeLists.txt中
    # set(elewise_common_tiling_files
    #         ${CANN_ROOT}/ops/built-in/op_tiling/runtime/elewise_tiling.cc
    #         )
    # 算子自己的tiling文件路径
    set(add_custom_tiling_files
        ${CMAKE_CURRENT_SOURCE_DIR}/../../../op_host/add_custom_tiling.cpp
        )
    # 使用AddOpTestCase
    # param1:算子名称,以kernel方式命名
    # param2:soc版本,多个以分号分隔,例如:"ascend910_95;ascend910b"
    # param3:自定义编译选项,一般填写测试的一种典型数据类型组合,不需要则传入空字符串,例如:"-DDTYPE_X=float",多个使用空格分隔,例如:"-DDTYPE_X=float -DDTYPE_Y=float"
    # param4:该算子依赖的所有tiling源码文件
    AddOpTestCase(add_custom "ascend910b" "-DDTYPE_X1=float -DDTYPE_X2=float -DDTYPE_Y=float" "${add_custom_tiling_files}")
endif()

执行测试:

cd Sources/ops-math;bash build.sh -u --opkernel --ops=add_custom --experimental

输出略。Infershape UT文件 tests/ut/op_host/test_add_custom_infershape.cpp 略过。

ST(系统测试)将算子集成到完整的系统环境中,验证算子在真实业务场景、端到端流程下的功能、性能、稳定性是否符合要求。需要编译部署算子,调用代码文件 examples/test_aclnn_add_custom.cpp 内容和前面部分调用算子API一样。

测试:

cd Sources/ops-math;source ${HOME}/vendors/custom_math/bin/set_env.bash;bash build.sh --run_example add_custom eager cust --vendor_name=custom --experimental
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。