Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

English | 中文版

1. 背景:NPU 编程的现状与挑战

为什么关注内存安全?

在异构计算领域,GPU/NPU 编程长期以来依赖 C/C++ 生态。CUDA、OpenCL、SYCL 等框架虽然功能强大,但继承了 C/C++ 的所有内存安全问题:悬垂指针、缓冲区溢出、数据竞争、资源泄漏。这些问题在异构环境中尤为棘手——设备内存与宿主内存的交互增加了额外的复杂性。

一次典型的 NPU 编程失误可能表现为:

// C++ AscendC: 忘记释放设备内存 → 内存泄漏
void* devPtr;
aclrtMalloc(&devPtr, size, ACL_MEM_MALLOC_HUGE_FIRST);
// ... 使用 devPtr 做计算 ...
// 如果这里发生异常,aclrtFree 永远不会被调用
aclrtFree(devPtr);

Rust 的所有权系统和 RAII(资源获取即初始化)模式能够在编译期消除这类问题。这正是 ascend-rs 项目的核心动机。

开源生态现状

目前,异构计算的内存安全编程领域已有一些探索:

项目目标硬件方法状态
rust-cudaNVIDIA GPURust → PTX 编译,CUDA 安全绑定不再活跃
rust-gpuGPU (Vulkan)Rust → SPIR-V 编译活跃
krnlGPU (Vulkan)安全的 GPU 计算内核活跃
cudarcNVIDIA GPUCUDA 运行时安全绑定活跃
ascend-rs华为昇腾 NPURust → MLIR → NPU 编译,ACL 安全绑定开发中

可以看到,昇腾 NPU 生态中,ascend-rs 是目前唯一一个尝试同时在宿主机端和设备端实现 Rust 内存安全编程的项目。 这填补了 Ascend 生态的一个重要空白。

ascend-rs 项目架构

ascend-rs 采用三层架构:

graph TD
    A["应用层<br/>用户的 Rust 程序"] --> B["宿主机 API 层<br/>ascend_rs + ascend_sys<br/>RAII 安全封装"]
    A --> C["设备运行时层<br/>ascend_std + rustc_codegen_mlir<br/>#![no_core] 运行时 | MLIR 代码生成后端"]
    B --> D["CANN SDK · C/C++ 底层库<br/>ACL Runtime · AscendCL · bisheng · bishengir · HIVM"]
    C --> D

宿主机 API 层通过 bindgen 自动生成 FFI 绑定,并在其上构建安全的 Rust 封装:AclDeviceAclContextAclStreamDeviceBuffer<T> 等,利用生命周期系统确保资源使用的正确顺序。

设备运行时层更具创新性:它包含一个自定义的 rustc 代码生成后端,将 Rust 代码编译为 MLIR。之后,mlir_to_cpp 翻译步骤将 MLIR 转换为带有 AscendC API 调用的 C++ 源码,再由 bisheng(CANN C++ 编译器)编译为 NPU 可执行二进制——昇腾 910B 和 310P 均采用这条路径。这条 MLIR-to-C++ 路径提供了完整的 AscendC 特性支持——DMA 操作、向量指令、流水线屏障和 TPipe 基础设施。翻译器识别 MLIR 中的 ascend_* 函数调用,并生成相应的 AscendC 向量操作。