pyACL:几行 Python 让你的模型跑在昇腾NPU上
·
本文基于昇腾CANN和昇腾NPU,围绕 pyACL Python 推理 技术展开。
ACLNN 是 C++ 接口,pyACL 是 Python 版的 AscendCL 封装。import acl 就能在 NPU 上加载 OM 模型并完成推理部署、管理 Tensor、提交推理、取回结果。用 NumPy 准备输入数据,pyACL 自动做 Host→Device 搬运——整个流程不用写一行 C++。
ACLNN 适合需要极致控制推理链路的场景,pyACL 适合快速验证和 Python 生态集成。两者的底层走的是同一套 ACL Runtime API。
第一个 pyACL 推理程序
# pyACL 推理——加载 ResNet-50 的 OM 模型
import acl
import numpy as np
# 1. 初始化 Runtime
acl.init()
acl.rt.set_device(0)
context, _ = acl.rt.create_context(0)
stream = acl.rt.create_stream()
# 2. 加载编译好的 OM 模型
model_id, model_desc = acl.mdl.load_from_file("resnet50.om")
# 3. 构造输入——NumPy 自动转 NPU Tensor
img = np.random.randn(1, 3, 224, 224).astype(np.float16)
input_buf, input_buf_id = acl.create_tensor(img)
input_ds = acl.mdl.create_dataset()
acl.mdl.add_dataset_buffer(input_ds, input_buf)
# 4. 分配输出 Buffer
out_size = acl.mdl.get_output_size_by_index(model_desc, 0)
out_buf, out_buf_id = acl.rt.malloc(out_size,
acl.ACL_MEM_MALLOC_NORMAL_ONLY)
out_ds = acl.mdl.create_dataset()
acl.mdl.add_dataset_buffer(out_ds, out_buf)
# 5. 异步推理
acl.mdl.execute_async(model_id, input_ds, out_ds, stream)
acl.rt.synchronize_stream(stream)
# 6. 取结果回 NumPy
result = acl.get_tensor_data(out_ds, 0) # NumPy ndarray
pred = np.argmax(result)
print(f"预测类别: {pred}")
# 7. 清理
acl.rt.free(out_buf)
acl.mdl.unload(model_id)
acl.rt.destroy_stream(stream)
acl.rt.destroy_context(context)
acl.rt.reset_device(0)
acl.finalize()
pyACL 的 Tensor 管理
acl.create_tensor(numpy_array) 做了三件事:在 NPU 显存上分配等量空间,把 NumPy 数据搬过去,返回 Device 侧 Buffer 指针和 ID。内部走 aclrtMemcpy 做 Host→Device 拷贝——跟 C++ 接口一致。
数据搬回去用 acl.get_tensor_data(dataset, index)——从输出 Dataset 里取第 index 个 Buffer,拷贝回 Host 返回 NumPy 数组。如果结果很大(比如 128K×4096 的 Logits),这一步是推理后最大的延迟来源——DDR → CPU 的 PCIe 带宽约 32GB/s(PCIe 4.0 x16)。
常见踩坑
acl.init()只能调一次。多进程部署时每个子进程独立 init,同一进程内重复 init 直接报错。- Tensor dtype 必须匹配 OM 模型。ATC 编译时指定 FP16,Python 端传 FP32 不会报错——但
acl.create_tensor不会自动转换,结果全乱。 - 异步执行要 sync。
execute_async之后取结果前必须synchronize_stream。忘了 sync 读到的是未初始化的显存。
跟 C++ ACLNN 的对比
pyACL 链路:
NumPy → acl.create_tensor → execute_async → get_tensor_data → NumPy
ACLNN 链路:
float[] → aclrtMemcpy → aclnnMatMul → aclrtMemcpy → float[]
底层是同一套 Runtime。区别在开发效率——pyACL 省了显存管理代码和 C++ 编译链路,但性能完全一致。
参考仓库
更多推荐



所有评论(0)