☰
CANNJudge 算子竞赛:从第一次算子提交到冲高分的完整手册
2026/10/20 1:55:20 网站建设 项目流程

CANNJudge 算子竞赛:从第一次算子提交到冲高分的完整手册

【免费下载链接】cann-learning-hubCANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。项目地址: https://gitcode.com/cann/cann-learning-hub

面向 CANNJudge 算子竞赛选手的实操参考:RSA 加密登录、三种算子提交方式、泛化算子设计,到 Wrong Answer 排查与提分。读完即可在 5 分钟内完成首次算子提交。

第一层|跑通一次提交

别追求完美,先跑通。三步:密钥、登录、提交。

环境与 RSA 密钥

CANNJudge 的 RSA 加密登录流程:服务器端保留私钥,你的个人电脑用公钥加密密码,密码全程不以明文传输。工具都在仓库的 skills/cannjudge-submit/ 目录下,用法见 references/rsa-login.md。

python3 generate_key.py # 一次性操作:生成 private.pem(留服务器)与 public.pem(发个人电脑) python3 encrypt_password.py --public-key public.pem # 按提示输入密码,得到 RSA 密文

私钥不要带出执行环境;会话过期后密文可复用,不用重新输入密码。

三种接入姿势,任选其一

  • CLI:命令行一把梭,速度最快。登录后依次下载模板、提交工程:
python3 cannjudge_cli.py login --email "you@example.com" --ciphertext "密文" --private-key private.pem python3 cannjudge_cli.py download --problem-url "<题目页链接>" --output ./add-work python3 cannjudge_cli.py submit --problem-url "<题目页链接>" --project-dir ./add-work/project

正式提交前先用submit --dry-run检查文件,提交后用query --submission-id ID查结果。下载器会拒绝覆盖已有工程,重新下载换个目录即可。

  • Python API:适合嵌进自己的脚本,最小调用长这样:
from cannjudge_cli import CANNJudgeClient client = CANNJudgeClient() client.login_with_ciphertext(email=EMAIL, ciphertext=CT, private_key_path="private.pem") submission_id = client.submit("add", tiling_h=tiling_h, host_cpp=host_cpp, kernel_cpp=kernel_cpp)
  • 示例脚本:python3 example.py,交互式引导走完全流程,第一次用建议选它。

登录成功后会话自动保存,后续下载、提交、查询、看排行榜都不用再输凭据。

第二层|读题不翻车

老手规矩:先读题十分钟,再碰键盘。题理解错了,代码全错。

题目三要素

  • 算子原型:输入输出与属性怎么定义,对齐哪个参考算子(如 torch.histc、tf.nn.depth_to_space)。
  • 数据类型:float16 / float32 等支持哪些 dtype,一个都不能漏。
  • 维度与属性:支持 4D 还是任意 rank,axis、keepdims 等属性取值有什么特殊语义。

以当次题目页面的签名、dtype、精度、CANN 版本和只读文件清单为准,别拿别题的规格硬套。Host 侧的InferShape要根据输入 shape 与属性算出输出 shape,它同样要泛化,否则隐藏用例会直接挂。

⚠️ 默认值雷区

陷阱类型错误理解正确理解
min=0, max=0范围是 [0,0]自动计算数据范围(torch.histc 语义)
axis=-1非法参数最后一个维度
keepdims=False默认值,不用管不保留被归约的维度
属性默认值直接当默认值用默认值本身可能就是特殊标志

先查参考算子官方文档,再用 Python 本地验证一遍边界行为,然后才写 C++。

工程骨架

工程骨架用 Ascend C 编写——昇腾的算子编程语言,代码最终编译成在 NPU AI Core 上跑的 kernel。下载的模板是标准目录:

code/ ├── CMakeLists.txt # 顶层 CMake 配置 ├── op_host/ │ ├── CMakeLists.txt │ └── {op_name}.cpp # Host 侧:TilingFunc、InferShape └── op_kernel/ ├── CMakeLists.txt ├── {op_name}_tiling.h # Tiling 数据结构 ├── tiling_key_{op_name}.h # Tiling Key 模板 └── {op_name}.cpp # Kernel 侧:实际计算
文件职责
{op_name}_tiling.h定义 Tiling 结构(切分参数),承载全部泛化参数
tiling_key_{op_name}.hTiling Key 模板,用于多核切分策略
op_host/{op_name}.cppHost 侧:TilingFunc、InferShape 等前置计算
op_kernel/{op_name}.cppKernel 侧:跑在 AI Core 上,执行实际计算

模板若缺CMakePresets.json或build.sh,从已有 Ascend C 工程复制后改路径即可。

第三层|泛化是硬功夫

平台不开放测试用例 API,本地看到的只是公开样例,隐藏用例随意出。所以泛化算子设计的目标,不是通过可见样例,而是覆盖题目签名下的全部合法输入。

泛化五板斧

  • Shape:不假设固定 rank,按总元素数处理。
  • Dtype:题目要求的每种数据类型都要实现,用模板统一逻辑。
  • 属性:枚举属性全部合法取值,含默认值与负值。
  • 对齐:32 字节对齐与非对齐尾部数据都要处理。
  • 边界:空输入、单元素、极端值,必须能跑。

对齐最容易被忽略:Ascend C 的 Vector 指令常以 32 字节为块操作,尾部不足一块的数据要走单独处理路径。

正误对照

// ❌ 硬编码:假定 4 维、只支持 float int32_t N = shape.GetDim(0); int32_t C = shape.GetDim(1); int32_t H = shape.GetDim(2); int32_t W = shape.GetDim(3); // ✅ 动态:任意 rank,模板化支持多 dtype int32_t rank = shape.GetDimNum(); uint32_t total = 1; for (int32_t i = 0; i < rank; ++i) { total *= shape.GetDim(i); }

Kernel 侧再配合GlobalTensor<T>使用——它是 Ascend C 对全局内存的封装,T 可实例化为 float / half。

提交前自查

  • Shape:不依赖固定 rank,任意大小可用
  • Dtype:覆盖题目要求的全部数据类型
  • 属性:含默认值在内的所有取值都覆盖
  • 对齐:32 字节对齐与非对齐尾部都处理
  • 边界:空输入、单元素、极端值全部通过

提交之后|状态、排错与提分

状态速查

状态含义建议操作
Running正在执行等几秒再查,别重复提交
Accepted(或Pass)全部通过记下精度比例与用时,评估名次
Wrong Answer部分用例失败走下面的三步排查
Compile Error编译失败检查语法与头文件,本地先修好
Runtime Error运行时错误检查内存访问越界与核数配置

别把Running当完成:默认提交后等 120 秒出结果,或用--no-wait分次查询。

Wrong Answer 三步排查

  1. 看精度比例:precision_ratio是否接近 1 但差一口气,判断是系统性误差还是边界误差。
  2. 看失败用例:对照哪个 dtype / shape 挂了,锁定出问题的维度。
  3. 看问题类型:归因到数据类型转换、属性理解还是算法逻辑,再对症下药。

拿不准就上 profiling:本地有 NPU 环境时,用 msprof 抓一段 timeline,哪个单元卡住一目了然。

提分三板斧

  • 多核并行:Ascend C 多核优化从 Tiling 切分开始,把总元素数切给多个 AI Core,别让单核干到底。
  • 减少 global memory 访问:数据按块搬进 L1 缓冲区,在 L1 里算完再写回,别逐元素来回跑 global memory。
  • 向量化指令:标量循环换成 Vector 单元指令,配合 double buffer 让搬运与计算重叠。

高频问题快查

Q:为什么部分测试用例失败?

A:算子不够泛化。依次检查:题目要求的 dtype 是否全支持、axis=-1 与空输入这类属性边界是否处理、默认值的特殊语义是否理解正确。本地公开样例过了、平台挂,多半是边界问题。

Q:float16 精度问题怎么处理?

A:float16 表示范围窄,边界值会被量化。两个动作:Host 侧按 dtype 设标志,Kernel 侧先把边界值舍入到 float16 可表示值再比较。

if (quantizeEdges) { // Host 侧按 dtype 设标志:float16 为 1,float32 为 0 half edge_h = static_cast<half>(edge); edge = static_cast<float>(edge_h); }

Q:模板缺编译配置怎么办?

A:CMakePresets.json从已有 Ascend C 工程复制后改路径;build.sh参考其他工程的脚本改。题目模板的只读文件清单要原样保留,别动只读文件。

Q:精度阈值是多少?

A:float16 一般要求 rtol < 1e-3、atol < 1e-3;float32 要求 rtol < 1e-4、atol < 1e-4。以题目页面的精度说明为准。

收个尾:你的行动路线

  1. 生成 RSA 密钥对,加密密码,完成首次登录。
  2. 挑一道简单的逐元素算子题,下载模板,把骨架跑起来。
  3. 提交第一版,拿到状态反馈。
  4. 看结果迭代:先修正确性,再调性能。

第一次提交只是起点,泛化站稳了,排行榜只是时间问题。

【免费下载链接】cann-learning-hubCANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。项目地址: https://gitcode.com/cann/cann-learning-hub

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询