
AsNumpy 架构深度解析Ascend NPU 上的 NumPy 三层设计、NPUArray 核心与 OpenBOAT 算子扩展策略【免费下载链接】asnumpy哈尔滨工业大学计算学部苏统华、王甜甜老师团队联合华为CANN团队开发的华为昇腾NPU原生Numpy仓库项目地址: https://gitcode.com/cann/asnumpyAsNumpy 是面向华为昇腾 NPU 的原生科学计算库目标是在 Python 层提供与numpy.ndarray完全一致的 API。本文基于 docs/architecture.md 展开系统讲解其三层软件架构、核心数据结构NPUArray的封装与资源管理机制、功能/基础双模块 API 布局以及借助 CANN 内建算子、Ascend C 自研算子与 OpenBOAT 开源算子库三层并进的 NPU 扩展策略。读完本文你将理解一次ap.multiply()调用从 Python 到昇腾硬件算子的完整链路并能据此评估如何在现有 NumPy 代码中迁移到 AsNumpy。一、三层架构从 Python 前端到昇腾硬件的完整调用链AsNumpy 采用清晰的三层分层设计将职责严格分离其总体结构如下------------------------------------------ | Python Frontend (src/asnumpy/*.py) | | - __init__.py 122 exported symbols | | - array.py array creation (10 fn) | | - math.py math ops (80 fn) | | - linalg/ linear algebra | | - random/ random sampling | | - logic.py logic functions (16 fn) | | - nn.py neural network (softmax) | | - statistics.py statistics (mean) | ------------------------------------------ | pybind11 binding layer (bindings/python/*.cpp) PYBIND11_MODULE(_core, ...) | ------------------------------------------ | C Core (csrc/, include/) | | - NPUArray core data structure | | - namespace asnumpy operator impls | | - Ascend ACL / ACLNN operator wrappers | | - CANN Runtime device management | ------------------------------------------ | Huawei CANN (ascendcl, runtime, nnopbase, opapi) | ------------------------------------------ | Ascend NPU Hardware (910B) | ------------------------------------------1. Python 前端面向用户的 NumPy 兼容 APIPython 层位于 src/asnumpy/是用户唯一直接接触的接口。其顶层命名空间通过 src/asnumpy/init.py 组织_EAGER_EXPORTS立即导出init、finalize、set_device、reset_device、reset_device_force五个设备生命周期函数其余 120 余个函数则通过_LAZY_MAPPING惰性导入__getattr__按需加载对应子模块既加快包导入速度也让ap.add、ap.sin、ap.sort等调用与 NumPy 的顶层命名保持一致。模块划分与文档标注的规模可对照源码核实math.py数学运算算术、三角函数、指数对数等 80 函数对应 C 命名空间asnumpy::array.py数组创建文档标注 10 个函数当前源码 src/asnumpy/init.py 的_LAZY_MAPPING中已注册empty、zeros、ones、full、eye、identity、linspace等 11 个导出logic.py16 个逻辑函数all、any、equal、logical_and等与文档数字完全一致linalg/、random/线性代数与随机抽样按子模块组织处于持续建设中nn.py、statistics.py当前以softmax、mean为代表sorting.py、io.py排序与文件读写。2. pybind11 绑定层Python 与 C 的桥梁绑定层位于 bindings/python/以PYBIND11_MODULE(_core, module)为入口见 bindings/python/module.cpp注册array、cann、fft、linalg、math、logic、random、sorting、statistics、nn、testing等子模块并分别调用bind_math、bind_logic等绑定函数把 C 算子实现暴露给 Python。绑定层还负责异常翻译std::invalid_argument转为 PythonValueError、std::out_of_range转为IndexError、std::bad_alloc转为MemoryError包含 error 的 ACL 运行时错误统一封装为CannErrorRuntimeError子类。这意味着用户在 Python 层捕获到的是语义明确的异常类型而非裸的 C 错误码。3. C 核心与 CANN算子执行与设备管理C 核心位于 csrc/ 与 include/asnumpy/NPUArray是核心数据结构asnumpy::命名空间承载算子实现算子通过 Ascend ACL / ACLNN 封装调用 CANN设备管理则由 CANN RuntimeaclInit/aclrtMalloc等负责。最底层是昇腾 910B NPU 硬件。一个典型算子实现的固定五步模式可以在 csrc/math/math.cpp 中反复看到以exp为例csrc/math/math.cpp#L131-L144按输入shape构造结果NPUArray调用aclnnExpGetWorkspaceSize查询算子工作空间大小若工作空间大于 0用aclrtMalloc分配执行aclnnExp传入 workspace 与aclOpExecutoraclrtSynchronizeDevice同步后返回结果。二、NPUArray核心数据结构的三项设计原则NPUArray是 AsNumpy 的核心数据结构围绕三条原则设计兼容性Compatibility、封装性Encapsulation与资源管理Resource Management。其声明见 include/asnumpy/utils/npu_array.hpp实现见 csrc/utils/npu_array.cpp。1. 兼容性与 NumPy 命名一致迁移只需改 importNPUArray在 Python 层暴露与numpy.ndarray相同的接口函数命名一一对应add、multiply、matmul……。迁移现有 NumPy 代码只需更换 import 并插入数据搬运调用例如import numpy as np import asnumpy as ap m1 np.random.normal(0, 1, (3000, 3000)).astype(np.float32) m2 np.random.normal(0, 1, (3000, 3000)).astype(np.float32) m1_npu ap.ndarray.from_numpy(m1) # CPU - NPU m2_npu ap.ndarray.from_numpy(m2) result ap.multiply(m1_npu, m2_npu) # NPU 上完成计算 print(result.to_numpy()) # NPU - CPU2. 封装性内部字段对用户透明NPUArray内部持有五个核心字段字段类型说明dtypepy::dtype元素类型Python 侧 NumPy dtypeaclDtypeaclDataType元素类型ACL 侧与dtype通过 dtype 表精确对应shapestd::vectorint64_t各维尺寸stridesstd::vectorint64_t内存布局行优先构造时从末维向前累乘得到tensorPtraclTensor*底层aclTensor指针devicePtr私有void*设备内存裸地址通过device_address()暴露用户不直接接触这些字段构造时先aclrtMalloc分配设备内存再用aclCreateTensor以ACL_FORMAT_ND格式创建aclTensor并绑定devicePtr见 csrc/utils/npu_array.cpp#L32-L52。零大小数组则传入nullptr数据指针避免无意义的设备内存申请。3. 资源管理RAII 消除手动内存管理NPUArray遵循 RAII析构函数自动调用aclDestroyTensor释放aclTensor、aclrtFree释放设备内存csrc/utils/npu_array.cpp#L238-L247用户无需也无法手动管理设备内存。同时完整实现了 C 四种值语义——拷贝构造、移动构造、拷贝赋值、移动赋值拷贝语义是深拷贝重新aclrtMalloc后经aclGetRawTensorAddr取源地址、ACL_MEMCPY_DEVICE_TO_DEVICE复制内容并aclrtSynchronizeDevice移动语义则转让所有权并将源对象置为失效状态。数据搬运两条关键路径FromNumpycsrc/utils/npu_array.cpp#L259读取 host 缓冲的buffer_info按ACL_MEMCPY_HOST_TO_DEVICE把数据拷入设备内存并同步流ToNumpycsrc/utils/npu_array.cpp#L287按ACL_MEMCPY_DEVICE_TO_HOST拷回 host。文档特别指出float16/BF16需要特殊的uint16_t解包——不过从当前实现看NumPyfloat16与ACL_FLOAT16同为 IEEE-754 binary16宿主与设备表示完全一致可直接按字节拷贝且ToNumpy在执行拷贝前会校验 host 缓冲字节数与设备张量字节数一致防止半精度数组被误写成 4 字节/元素csrc/utils/npu_array.cpp#L296-L305。dtype 转换由 include/asnumpy/dtypes/dtype_table.hpp 中注册的映射表统一负责AclFromNumpy与NumpyFromAcl在受支持的 14 种 dtype 集合上互为精确逆映射这是算子层可以放心做aclDataType - NumPy dtype - aclDataType往返转换而不丢精度的前提无 NumPy 等价的 ACL 类型bf16、fp8/fp6/fp4、int4、uint1、complex32会被显式拒绝而非静默放宽。三、API 架构功能模块 基础模块的双层布局AsNumpy 的 API 划分为功能模块与基础模块两层。功能模块面向科学计算主领域模块Python 入口C 命名空间状态数学算术、三角、指数、对数math.pyasnumpy::已完成线性代数linalg/全局进行中随机抽样random/全局进行中逻辑函数logic.pyasnumpy::已完成数组创建array.py全局已完成排序sorting.py全局已完成神经网络nn.pyasnumpy::已完成softmax统计statistics.pyasnumpy::已完成meanI/Oio.py委托 NumPy已完成功能模块的 C 侧同样按领域拆分实现与绑定例如 csrc/math/ 下按三角函数、双曲函数、指数对数、取整、算术运算、复数处理等 13 个子文件组织bindings/python/bind_math.cpp 再逐一math.def(sin, Sin, ...)绑定clip还针对数组/标量四种组合提供了重载bindings/python/bind_math.cpp#L90-L97。基础模块支撑功能层模块职责NPUArraycsrc/utils/核心数据结构CANN drivercsrc/cann/设备初始化与生命周期管理dtypescsrc/dtypes/数据类型注册pybind11 bindingsbindings/python/Python-C 接口其中 CANN driver 实现了aclInit/aclFinalize与日志初始化Python 包导入时自动执行init()与set_device(0)见 src/asnumpy/init.py 末尾进程退出时经atexit注册的reset()统一reset_device(0)与finalize()init失败会抛出带 ACL 错误码与最近错误信息的std::runtime_error见 csrc/cann/driver.cpp。用户也可通过 src/asnumpy/cann.py 暴露的set_device、reset_device、reset_device_force手动切换设备。四、NPU 扩展模块三层并进补齐算子缺口CANN 内建算子主要为深度学习训练与推理设计而 AsNumpy 面向通用科学计算——数据分析、数值方法、信号处理——所需的算子集合远大于 CANN 单独提供的范围。缺口The gapCANN 内建算子无法覆盖 NumPy 的全部 API 面。三层并进策略The strategy直接封装现有 CANN 内建算子——绝大多数基础运算add、multiply、exp、sin、reduce_sum等走这条路径这也是上文提到的aclnnXxxGetWorkspaceSize aclnnXxx模式用 Ascend C 手工开发缺失算子——对 CANN 未提供的算子以昇腾 Ascend C 编程语言自研补齐以 OpenBOAT 开源算子库补充——复用同一研究团队维护的开源算子库扩大覆盖面。价值The value这种封装 自研 复用的三管齐下方式逐步缩小兼容性差距向 v1.0 覆盖 NumPy 使用频率最高的 Top-100 API 的目标持续推进。从算子组合的实现细节还能看到部分高阶函数本身就是由多个基础 ACLNN 算子组合而成例如nansum先用aclnnNanToNum把 NaN 清零再经aclnnReduceSum规约、aclnnCast转换 dtype见 csrc/math/math.cpphypot则由两次aclnnMula²、b²、一次aclnnAdd、一次aclnnSqrt四步拼出csrc/math/math.cpp#L515-L632。这正体现了缺口策略在算子组合层面的价值——CANN 没有的语义可由已有基础算子编排实现。五、OpenBOAT同源算子库协同演进OpenBOAT 是由**哈尔滨工业大学计算学部 AISS 组苏统华教授团队**构建并维护的开源 Ascend C 算子库与 AsNumpy 由同一研究团队开发保证集成紧密度与路线图协调一致。属性详情项目地址https://link.gitcode.com/i/4f88e51030bab2fe6f9bd3343a3b08c2团队HIT 计算学部 AISS 组苏统华教授团队技术栈华为 Ascend C 编程语言在 AsNumpy 中的角色提供 CANN 内建算子未覆盖的算子实现拓宽 NumPy API 兼容面从图与项目结构看OpenBOAT 补充的算子示例包括cholesky、svd、trace、solve、isscalar、fft2、hfft等聚焦线性代数分解、矩阵求解与傅里叶变换等通用科学计算高频但 CANN 内建算子覆盖不足的方向。由于同一团队同时维护 AsNumpy 与 OpenBOAT二者的算子对接与能力规划可以同步推进这也是 AsNumpy 能够在轻量封装的同时持续扩大 NumPy API 兼容面的关键组织保障。六、总结AsNumpy 的架构可以用一句话概括Python 前端保证 API 兼容pybind11 绑定层桥接语言边界C 核心以 RAII 的NPUArray管理设备资源并封装 CANN 算子最后以内建封装 Ascend C 自研 OpenBOAT 复用三层策略补齐算子缺口。这套设计让开发者能够以近乎零成本的方式把 NumPy 代码迁移到昇腾 NPU 上执行——只改 import、插入from_numpy/to_numpy数据搬运即可。想要进一步动手实践可参考 docs/quick_start.md 的快速上手指南、examples/ 下的可运行示例脚本01_add.py、02_exp2.py、10_sort.py等以及 docs/benchmarks.md 中ap.mean()在大规模数据下的性能复现方法开发者若计划贡献新算子docs/developer_guide.md 提供了构建说明与编码规范。【免费下载链接】asnumpy哈尔滨工业大学计算学部苏统华、王甜甜老师团队联合华为CANN团队开发的华为昇腾NPU原生Numpy仓库项目地址: https://gitcode.com/cann/asnumpy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考