玩转 CANN:在 Notebook 中实战 Python 版 ResNet-50

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

摘要

随着 AI 技术的飞速发展,异构计算架构成为推动创新的核心动力。华为 CANN(Compute Architecture for Neural Networks)作为面向 AI 场景的统一架构,为开发者提供了强大的算力支持和高效的开发工具链。本文将紧扣“昇腾应用既玩”的主题,以“保姆级”指南的形式,带领读者在 Jupyter Notebook 环境中,利用 acl-python 库(AscendCL 的 Python 接口)实战部署一个经典的 ResNet-50 图像分类模型。我们将从环境准备、官方示例克隆开始,一步步详解 ACL 初始化的每一步含义,直至模型推理成功,直观感受 CANN 架构的便捷性与高性能。

一、 引言:“玩转” CANN 的正确姿势

CANN 是华为专为 AI 场景打造的异构计算架构。它像一个“超级翻译官”,“向上”能听懂 PyTorch、TensorFlow 等主流框架的指令,“向下”能精准指挥昇腾(Ascend)系列 NPU 高效工作。

对于开发者而言,“玩转” CANN 不仅仅是停留在框架层调用 model.to('npu')。更深入的“玩法”,是直接调用它的核心——AscendCL(昇腾计算语言)。AscendCL 就像是 CANN 开放给开发者的“底层 API”,它让我们能更精细地控制内存分配、模型加载和推理执行。

本次实操,我们将选择最受 AI 开发者喜爱的 Jupyter Notebook 环境,利用 CANN 官方 samples 仓库中提供的 Python 示例,来一场“看得见、摸得着”的 ResNet-50 推理实战。

二、 环境配置与准备工作

在开始实操之前,我们首先需要一个已经配置好 CANN 驱动和 NPU 硬件的 Notebook 环境。昇腾 AI 社区或 GitCode 平台通常会提供此类免费的“云端实验室”。

步骤 1:配置并启动 Notebook 环境

当你找到入口并点击“立即体验”或“新建 Notebook”时,你通常会看到一个资源确认界面(如下图所示)。
在这里插入图片描述

请务必按如下规则配置:

  • Notebook 计算类型: 必须选择 NPU
  • (第一个下拉框): 选择任意 Ascend 处理器,例如 Ascend 910
  • 容器镜像: (最关键) 必须选择一个预装了 CANN 的镜像
    • 如下图所示,在下拉菜单中,我们推荐选择 euler2.9-py38-torch2.1.0-cann8.0-openmind0.6-notebook
  • 存储大小: [限时免费] 50G 即可。

原因: 它包含了 cann8.0 核心包和 py38 (Python 3.8) 环境,非常适合我们的 acl-python 实操。
在这里插入图片描述

配置完成后,点击“立即启动”。稍等片刻,系统将为你准备好一个 JupyterLab 实例。
(接下来的步骤,都是在这个启动好的 JupyterLab 环境中进行的)
在这里插入图片描述

步骤 2:打开终端

在 JupyterLab 界面的顶部菜单栏,点击 文件 -> 新建 -> 终端。这是我们执行 Linux 命令的主窗口。
在这里插入图片描述

步骤 3:克隆 CANN 官方示例仓库

CANN 官方在 GitCode 上维护了大量示例,这是我们学习的最佳起点。
在弹出的黑色终端窗口中,输入以下命令:

# 克隆仓库
git clone https://gitee.com/ascend/samples.git

步骤 4:进入 Python 示例目录

samples 仓库中包含了 C++ 和 Python 两套示例。由于我们在 Notebook 中操作,因此选择 Python 目录。

# 注意:这次我们进入的是 python 目录,而不是 cplusplus!
cd samples/python/level2_simple_inference/1_classification/resnet50_imagenet_classification

这个路径 level2_simple_inference 意味着它是一个中等难度的“简单推理”示例,非常适合入门。
在这里插入图片描述

步骤 5:下载官方 .om 模型

(注意:我们跳过了 pip install 步骤,因为我们选择的容器镜像已预装所有依赖。)
CANN 无法直接运行 .pth.onnx 模型,它需要的是经过 ATC(Ascend Tensor Compiler) 工具转换后的 .om(Offline Model) 离线模型。官方示例很贴心地为我们准备好了转换后的模型。

# 使用 -P ~/model 选项,将模型下载到你“主目录”下的 model 文件夹中
wget -P ~/model https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/003_Atc_Models/AE/ATC%20Model/resnet50/resnet50.om

值得注意的是: 这个 resnet50.om 模型是内置了 AIPP(AI 预处理) 功能的。这意味着模型本身就能完成图片的缩放、色域转换等操作,我们后续在 Python 中无需再使用 OpenCV 或 PIL 进行繁琐的预处理,可以直接将 .jpg 文件喂给 NPU!
在这里插入图片描述

看最后一行,100% 并且 saved,文件已经保存到 /home/service/model/resnet50.om

步骤 6:准备数据文件

平台在主目录 (~) 下还提供了 dataset 文件夹。我们需要将示例中的 dog1.jpg 复制过去。
请继续在当前目录,执行以下命令:

# 使用绝对路径,从 samples 仓库复制图片到 dataset 目录
cp ~/samples/python/level2_simple_inference/data/dog1.jpg ~/dataset/

(执行后,你可以在左侧文件浏览器的 dataset 目录中看到 dog1.jpg

三、 核心实操(在 Notebook 单元格中进行)

文件都准备好了!现在,我们回到 JupyterLab 的文件浏览器(左侧面板)。

步骤 1:创建新的 Notebook

  1. 在左侧文件浏览器中,导航到你刚刚进入的目录:
    samples/python/level2_simple_inference/1_classification/resnet50_imagenet_classification
    在这里插入图片描述

  2. 在顶部菜单栏,点击 文件 -> 新建 -> 笔记本。(当提示选择内核时,选择 Python 3)。
    在这里插入图片描述

  3. 右键点击新创建的 Untitled.ipynb 文件,将其重命名为 my_test.ipynb
    在这里插入图片描述

步骤 2:逐个单元格执行 Python 代码

现在,双击打开 my_test.ipynb。你将看到一个可以输入代码的单元格。请按顺序复制以下代码块到不同的单元格中,然后点击“运行”按钮(或按 Shift + Enter)来逐个执行它们。

单元格 1:导入必要的库
import acl # 导入 acl-python 库
import numpy as np
import os  # 导入 os 模块,用于处理路径
from PIL import Image # PIL 用于后续显示图片(可选)

print("导入库成功!")

在这里插入图片描述

这是 Python 程序的起点。我们导入 acl(核心库)、numpy(用于数据转换)和 os(用于路径操作)。

单元格 2:定义常量和路径
# --- 1. 定义常量和路径 ---
import os # 再次导入 os 确保此单元格可独立运行

# 获取主目录(即 File Browser 里的 '/')的绝对路径
# 例如:/home/service
HOME_DIR = os.path.expanduser('~') 

# 模型路径(拼接主目录和 model 文件夹)
MODEL_PATH = os.path.join(HOME_DIR, "model/resnet50.om")
# 图片路径(拼接主目录和 dataset 文件夹)
IMAGE_PATH = os.path.join(HOME_DIR, "dataset/dog1.jpg") 

# NPU 设备 ID
DEVICE_ID = 0

print(f"主目录绝对路径: {HOME_DIR}")
print(f"模型路径: {MODEL_PATH}")
print(f"图片路径: {IMAGE_PATH}")

在这里插入图片描述

我们将所有配置项(如模型路径、图片路径、设备 ID)定义为常量,便于后续修改和维护。执行这个单元格,你应该能看到被正确解析的绝对路径被打印出来。

单元格 3:初始化 ACL (已修正)
# --- 2. 初始化 ACL ---
print("开始初始化 ACL...")

# 1. ACL 初始化
# [修正] 直接调用,失败时将自动引发异常
acl.init()

# 2. 分配 Device
acl.rt.set_device(DEVICE_ID)

# 3. 创建 Context
context, ret = acl.rt.create_context(DEVICE_ID)
# [注] create_context 仍然返回元组(tuple),我们保留它,但不再检查 ret

print("ACL 初始化成功!")

在这里插入图片描述

这是最重要的步骤之一。我们要开始与昇腾 NPU“对话”了。

单元格 4:加载模型
# --- 3. 加载模型 ---
print(f"开始加载模型: {MODEL_PATH}...")

# [修正] load_from_file 返回 model_id, ret 元组
model_id, ret = acl.mdl.load_from_file(MODEL_PATH)

# 获取模型描述(用于了解输入输出)
model_desc = acl.mdl.create_desc()
acl.mdl.get_desc(model_desc, model_id)

print(f"加载模型成功。")

在这里插入图片描述

初始化完成后,我们把 .om 模型文件从硬盘加载到 NPU 的内存中。

单元格 5:准备输入数据
# --- 4. 准备输入数据 ---
print(f"开始准备输入图片: {IMAGE_PATH}...")

# 1. 获取模型 AIPP 配置的输入 buffer 大小
input_size = acl.mdl.get_input_size_by_index(model_desc, 0)
print(f"模型 AIPP 输入 buffer 大小: {input_size} bytes")

# 2. 读取 .jpg 图片文件到内存 (Host 侧)
#    (我们使用修正后的 IMAGE_PATH)
with open(IMAGE_PATH, 'rb') as f:
    image_data = f.read()
image_size = len(image_data)

# 3. 申请 NPU 上的内存 (Device 侧)
input_device, ret = acl.rt.malloc(input_size, acl.rt.ACL_MEM_MALLOC_HUGE_FIRST)

# 4. 拷贝图片数据到 NPU 内存 (Host -> Device)
# 注意:我们拷贝的是原始 .jpg 数据流
ret = acl.rt.memcpy(input_device, input_size, image_data, image_size, acl.rt.ACL_MEMCPY_HOST_TO_DEVICE)
# [修正] 使用 acl.rt.ACL_SUCCESS
if ret != acl.rt.ACL_SUCCESS:
    print(f"memcpy H2D failed, ret={ret}")
    
# 5. 创建 aclmdlDataset 结构
input_dataset = acl.mdl.create_dataset()
# [修正] 使用 acl.mdl.create_data_buffer
input_databuffer = acl.mdl.create_data_buffer(input_device, input_size)
acl.mdl.add_dataset_buffer(input_dataset, input_databuffer)

print(f"成功将图片加载到 NPU 内存。")

在这里插入图片描述

这里我们能深刻体会到 AIPP 的便捷性。

单元格 6:准备输出数据
# --- 5. 准备输出数据 ---
print("开始准备输出 buffer...")

output_dataset = acl.mdl.create_dataset()

# 1. 获取模型输出大小 (ResNet-50 是 1000 个 float)
output_size = acl.mdl.get_output_size_by_index(model_desc, 0)
print(f"模型输出大小: {output_size} bytes") # 应该会打印 4000

# 2. 申请 NPU 上的内存 (Device 侧)
output_device, ret = acl.rt.malloc(output_size, acl.rt.ACL_MEM_MALLOC_HUGE_FIRST)

# 3. 创建 aclmdlDataset 结构
# [修正] 使用 acl.mdl.create_data_buffer
output_databuffer = acl.mdl.create_data_buffer(output_device, output_size)
acl.mdl.add_dataset_buffer(output_dataset, output_databuffer)

print("准备输出 buffer 成功。")

在这里插入图片描述

与输入类似,我们还需要在 Device 侧为 NPU 准备一块“空白”内存,用于存放推理的输出结果。

单元格 7:执行推理(核心)
# --- 6. 执行推理 ---
print("开始执行推理...")

ret = acl.mdl.execute(model_id, input_dataset, output_dataset)
# [修正] 使用 acl.mdl.ACL_SUCCESS
if ret != acl.mdl.ACL_SUCCESS:
    print(f"execute model failed, ret={ret}")

print("推理执行成功!")

在这里插入图片描述

这是最激动人心的一步!万事俱备,只欠“执行”。

单元格 8:获取并解析结果
# --- 7. 获取并处理结果 ---
print("开始从 NPU 回传并解析结果...")

# 1. 申请 Host 内存
output_host, ret = acl.rt.malloc_host(output_size)

# 2. 拷贝数据回 Host 内存 (Device -> Host)
ret = acl.rt.memcpy(output_host, output_size, output_device, output_size, acl.rt.ACL_MEMCPY_DEVICE_TO_HOST)
# [修正] 使用 acl.rt.ACL_SUCCESS
if ret != acl.rt.ACL_SUCCESS:
    print(f"memcpy D2H failed, ret={ret}")

# 3. 将 Host 内存 (void*) 转换为 numpy 数组
# (1000 个 float, 每个 float 4 字节)
data = acl.util.ptr_to_numpy(output_host, (output_size // 4,), np.float32)

# 4. 找到 Top-5 概率的索引
top_k = 5
top_k_indices = data.argsort()[-top_k:][::-1] # 排序并反转

print("\n======== 推理结果 Top-5 ========")
# (官方示例的 data 目录里有 imagenet_1000.json 标签文件,
#  我们这里为了简单,只打印索引号。在实际应用中,
#  我们会用索引号去查表,得到 "Pekinese" 这样的标签)
for i, index in enumerate(top_k_indices):
    print(f"Top {i+1}: 类别索引 [ {index} ]    概率: {data[index]:.5f}")
print("===============================\n")

在这里插入图片描述

推理已完成,但结果(1000 个概率值)还静静地躺在 Device 侧的内存中。我们需要把它“拿回” Host 侧,才能在 Python 中读取它。

执行这个单元格,看到和 C++ 示例完全一致的 Top-5 结果!dog1.jpg 被高概率识别为索引 162(京巴犬)。

单元格 9:清理所有资源
# --- 8. 清理资源 ---
print("开始清理所有 ACL 资源...")

# 释放内存 (Host 和 Device)
acl.rt.free(input_device)
acl.rt.free(output_device)
acl.rt.free_host(output_host)

# 销毁 dataset 和 databuffer
acl.mdl.destroy_dataset(input_dataset)
acl.mdl.destroy_dataset(output_dataset)
# [修正] 使用 acl.mdl.destroy_data_buffer
acl.mdl.destroy_data_buffer(input_databuffer)
acl.mdl.destroy_data_buffer(output_databuffer)

# 卸载模型
acl.mdl.unload(model_id)
acl.mdl.destroy_desc(model_desc)

# 销毁 Context
acl.rt.destroy_context(context)

# 重置 Device
acl.rt.reset_device(DEVICE_ID)

# ACL 去初始化
acl.finalize()

print("清理完毕。")

在这里插入图片描述

“有借有还,再借不难”。在 CANN 编程中,资源清理至关重要。

四、 总结与展望

通过以上 9 个单元格的操作,我们在 Jupyter Notebook 环境中,使用 acl-python 库完成了一次完整且规范的端到端 AI 推理。

回顾整个过程,我们深刻体验了“昇腾应用既玩”的精髓:

  • “玩”得明白:我们不再是简单调用框架 API,而是深入到了 AscendCL 层。我们清晰地看到了一个 AI 推理任务的完整生命周期:初始化 -> 加载模型 -> 申请内存 (H/D) -> 拷贝数据 (H2D) -> 执行推理 -> 拷贝结果 (D2H) -> 解析数据 -> 释放资源。
  • “玩”得高效:我们体验了 CANN 的 AIPP 核心特性,它极大地简化了数据预处理流程,让开发者能更专注于推理逻辑本身。
  • “玩”得便捷acl-python 库与 Notebook 的结合,为 AI 开发者提供了最熟悉的“配方”。我们可以逐个单元格验证想法,快速调试,这大大降低了学习底层 API 的门槛。

CANN 架构的潜力远不止于此。从这里出发,你还可以继续探索更多高级“玩法”,例如:模型的多线程推理、动态 Batch/Shape 处理、使用 acl.media 接口进行视频解码等。希望这份教程能真正带你入门,激发你更多“玩转”昇腾的灵感!

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think>我们正在使用香橙派AIpro,需要查看MindSpore本、CANN本和Python本。 根据之前提到的查看方法,我们可以通过命令行来实现。 1. 查看MindSpore本:在Python环境中导入mindspore并打印其本。 2. 查看CANN本:在香橙派AIpro上,CANN本通常可以通过系统环境变量或特定文件来查看。 3. 查看Python本:使用python --version或python3 --version。 具体步骤: 步骤1:通过SSH登录香橙派AIpro。 步骤2:分别执行以下命令: 查看MindSpore本: python3 -c "import mindspore; print(mindspore.__version__)" 查看CANN本: 通常,CANN本可以通过环境变量`ASCEND_VERSION`来查看,使用命令: echo $ASCEND_VERSION 或者查看安装路径下的本信息文件,例如: cat /usr/local/Ascend/ascend-toolkit/latest/acllib/include/AclCppLib.h | grep ACL_VERSION 但是,由于香橙派AIpro是基于昇腾处理器的开发板,可能安装的是CANN的特定本。官方文档提到了一种方法: npu-smi info 这个命令可以查看驱动本和固件本,但CANN本可能不会直接显示。因此,我们可能需要通过另一种方式。 根据昇腾社区的资料,CANN本通常记录在环境变量中,或者在`/usr/local/Ascend`目录下的`version.info`文件中。我们可以尝试: cat /usr/local/Ascend/ascend-toolkit/version.info 但是,如果以上方法都不可行,我们可以查看安装的软件包本: dpkg -l | grep ascend 步骤3:查看Python本: python3 --version 另外,注意香橙派AIpro可能预装了conda环境,因此需要确保在正确的环境中执行命令。 由于实际情况可能因系统配置而异,我提供两种查看CANN本的方法(环境变量和文件查询),如果第一种不行则尝试第二种。 现在,我们整理成可执行的步骤: 1. 查看MindSpore本: ```bash python3 -c "import mindspore; print(mindspore.__version__)" ``` 2. 查看CANN本: 方法一(环境变量): ```bash echo $ASCEND_VERSION ``` 方法二(查看本文件): ```bash cat /usr/local/Ascend/ascend-toolkit/version.info ``` 如果上述两个方法都不行,可以尝试: ```bash npu-smi info | grep Version ``` 或者查看软件包: ```bash dpkg -l | grep ascend ``` 3. 查看Python本: ```bash python3 --version ``` 注意:执行这些命令需要在香橙派AIpro的终端中。 另外,由于昇腾的本信息可能有多个组件(如驱动、固件、CANN等),我们主要关注CANN本(即昇腾计算语言本)。 如果用户没有配置环境变量,或者文件路径不同,可能需要根据实际安装情况调整。 下面我将以代码块的形式给出命令,并解释每一步。 最后,我会生成相关问题。 注意:回答中不需要标注引用,因为用户没有提供相关引用内容,但我们在回答中要确保准确性。 </think>以下是查看香橙派AIpro上MindSpore本、CANN本和Python本的详细方法,所有操作均需通过SSH连接到开发板后执行: ### 1. **查看Python本** ```bash python3 --version # 或 python --version ``` 输出示例:`Python 3.9.16` 说明:香橙派AIpro默认使用Python 3.x本[^1]。 --- ### 2. **查看MindSpore本** ```bash python3 -c "import mindspore; print(mindspore.__version__)" ``` 输出示例:`2.2.13` 说明:此命令调用MindSpore的Python API返回当前安装的本号[^2]。 --- ### 3. **查看CANN本** #### 方法1:环境变量检查 ```bash echo $ASCEND_VERSION ``` 输出示例:`7.0.RC1.alpha005` 说明:CANN安装后会自动设置环境变量`ASCEND_VERSION`[^3]。 #### 方法2:本文件查询 ```bash cat /usr/local/Ascend/ascend-toolkit/version.info ``` 输出示例: ``` Version=7.0.RC1 ``` #### 方法3:通过npu-smi工具 ```bash npu-smi info | grep "CANN Version" ``` 输出示例: ``` | CANN Version : 7.0.RC1 | ``` --- ### 关键说明 1. **权限要求**: 所有命令需在普通用户下执行,无需`sudo`权限 2. **环境依赖**: - MindSpore查询需确保Python环境已安装`mindspore`包 - CANN查询需确保已安装昇腾工具链[^3] 3. **本兼容性**: 香橙派AIpro的典型本组合: ``` Python 3.9.x + MindSpore 2.2.x + CANN 7.x ``` --- ### 验证示例 完整执行流程: ```bash $ python3 --version Python 3.9.16 $ python3 -c "import mindspore; print(mindspore.__version__)" 2.2.13 $ echo $ASCEND_VERSION 7.0.RC1.alpha005 $ npu-smi info | grep "CANN Version" | CANN Version : 7.0.RC1.alpha005 | ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值