CANN 8.0.0 调研记录

CANN 版本兼容性

RC 模式和 EP 模式

安装说明

resnet50_run_app.py

import os

import acl
import numpy as np
from PIL import Image

ACL_MEM_MALLOC_HUGE_FIRST = 0
ACL_MEMCPY_HOST_TO_DEVICE = 1
ACL_MEMCPY_DEVICE_TO_HOST = 2


class net:
    def __init__(self, model_path):
        # 初始化函数
        self.device_id = 0

        # step1: 初始化
        ret = acl.init()
        # 指定运算的Device
        ret = acl.rt.set_device(self.device_id)

        # step2: 加载模型,本示例为ResNet-50模型
        # 加载离线模型文件,返回标识模型的ID
        self.model_id, ret = acl.mdl.load_from_file(model_path)
        # 创建空白模型描述信息,获取模型描述信息的指针地址
        self.model_desc = acl.mdl.create_desc()
        # 通过模型的ID,将模型的描述信息填充到model_desc
        ret = acl.mdl.get_desc(self.model_desc, self.model_id)

        # step3:创建输入输出数据集
        # 创建输入数据集
        self.input_dataset, self.input_data = self.prepare_dataset('input')
        # 创建输出数据集
        self.output_dataset, self.output_data = self.prepare_dataset('output')

    def prepare_dataset(self, io_type):
        # 准备数据集
        if io_type == "input":
            # 获得模型输入的个数
            io_num = acl.mdl.get_num_inputs(self.model_desc)
            acl_mdl_get_size_by_index = acl.mdl.get_input_size_by_index
        else:
            # 获得模型输出的个数
            io_num = acl.mdl.get_num_outputs(self.model_desc)
            acl_mdl_get_size_by_index = acl.mdl.get_output_size_by_index
        # 创建aclmdlDataset类型的数据,描述模型推理的输入。
        dataset = acl.mdl.create_dataset()
        datas = []
        for i in range(io_num):
            # 获取所需的buffer内存大小
            buffer_size = acl_mdl_get_size_by_index(self.model_desc, i)
            # 申请buffer内存
            buffer, ret = acl.rt.malloc(buffer_size, ACL_MEM_MALLOC_HUGE_FIRST)
            # 从内存创建buffer数据
            data_buffer = acl.create_data_buffer(buffer, buffer_size)
            # 将buffer数据添加到数据集
            _, ret = acl.mdl.add_dataset_buffer(dataset, data_buffer)
            datas.append({"buffer": buffer, "data": data_buffer, "size": buffer_size})
        return dataset, datas

    def forward(self, inputs):
        # 执行推理任务
        # 遍历所有输入,拷贝到对应的buffer内存中
        input_num = len(inputs)
        for i in range(input_num):
            bytes_data = inputs[i].tobytes()
            bytes_ptr = acl.util.bytes_to_ptr(bytes_data)
            # 将图片数据从Host传输到Device。
            ret = acl.rt.memcpy(self.input_data[i]["buffer"],   # 目标地址 device
                                self.input_data[i]["size"],     # 目标地址大小
                                bytes_ptr,                      # 源地址 host
                                len(bytes_data),                # 源地址大小
                                ACL_MEMCPY_HOST_TO_DEVICE)      # 模式:从host到device
        # 执行模型推理。
        ret = acl.mdl.execute(self.model_id, self.input_dataset, self.output_dataset)
        # 处理模型推理的输出数据,输出top5置信度的类别编号。
        inference_result = []
        for i, item in enumerate(self.output_data):
            buffer_host, ret = acl.rt.malloc_host(self.output_data[i]["size"])
            # 将推理输出数据从Device传输到Host。
            ret = acl.rt.memcpy(buffer_host,                    # 目标地址 host
                                self.output_data[i]["size"],    # 目标地址大小
                                self.output_data[i]["buffer"],  # 源地址 device
                                self.output_data[i]["size"],    # 源地址大小
                                ACL_MEMCPY_DEVICE_TO_HOST)      # 模式:从device到host
            # 从内存地址获取bytes对象
            bytes_out = acl.util.ptr_to_bytes(buffer_host, self.output_data[i]["size"])
            # 按照float32格式将数据转为numpy数组
            data = np.frombuffer(bytes_out, dtype=np.float32)
            inference_result.append(data)
            # 释放内存
            ret = acl.rt.free_host(buffer_host)
        vals = np.array(inference_result).flatten()
        # 对结果进行softmax转换
        vals = np.exp(vals)
        vals = vals / np.sum(vals)

        return vals

    def __del__(self):
        # 析构函数 按照初始化资源的相反顺序释放资源。
        # 销毁输入输出数据集
        for dataset in [self.input_data, self.output_data]:
            while dataset:
                item = dataset.pop()
                ret = acl.destroy_data_buffer(item["data"])    # 销毁buffer数据
                ret = acl.rt.free(item["buffer"])              # 释放buffer内存
        ret = acl.mdl.destroy_dataset(self.input_dataset)      # 销毁输入数据集
        ret = acl.mdl.destroy_dataset(self.output_dataset)     # 销毁输出数据集
        # 销毁模型描述
        ret = acl.mdl.destroy_desc(self.model_desc)
        # 卸载模型
        ret = acl.mdl.unload(self.model_id)
        # 释放device
        ret = acl.rt.reset_device(self.device_id)
        # acl去初始化
        ret = acl.finalize()


def transfer_pic(input_path):
    # 图像预处理
    input_path = os.path.abspath(input_path)
    with Image.open(input_path) as image_file:
        # 缩放为224*224
        img = image_file.resize((224, 224))
        # 转换为float32类型ndarray
        img = np.array(img).astype(np.float32)
    # 根据imageNet图片的均值和方差对图片像素进行归一化
    img -= [123.675, 116.28, 103.53]
    img /= [58.395, 57.12, 57.375]
    # RGB通道交换顺序为BGR
    img = img[:, :, ::-1]
    # resnet50为色彩通道在前
    img = img.transpose((2, 0, 1))
    # 返回并添加batch通道
    return np.array([img])


def print_top_5(data):
    top_5 = data.argsort()[::-1][:5]
    print("======== top5 inference results: =============")
    for j in top_5:
        print("[%d]: %f" % (j, data[j]))


if __name__ == "__main__":
    resnet50 = net('./model/resnet50.om')
    image_paths = ["./data/dog1_1024_683.jpg", "./data/dog2_1024_683.jpg"]
    for path in image_paths:
        # 图像预处理,此处仅供参考,用户按照自己需求进行预处理
        image = transfer_pic(path)
        # 将数据按照每个输入的顺序构造list传入,当前示例的ResNet-50模型只有一个输入
        result = resnet50.forward([image])
        # 输出top_5
        print_top_5(result)

    del resnet50

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值