MindSpore论坛报错活动第三十期-报错:使用MindSpore将.ckpt转.air再转.om出现AttributeError: 'AclLiteModel' object has no attribute '_is_destroye

1.系统环境

硬件环境(Ascend/GPU/CPU): Ascend
MindSpore版本: mindspore=2.4.1
执行模式(动态图):GRAPH
Python版本: Python=3.9.20
操作系统平台: linux arrch64

2.报错信息

2.1问题描述

1.主要异常

问题出现在 AclLiteModel 类的 _init_resource 方法中。具体来看,调用acl.mdl.load_from_file 函数失败,并返回了错误代码 145001。

2.析构异常

在 AclLiteModel.del 方法中,销毁对象时试图访问 _is_destroyed属性,但该属性不存在。

2.2 报错脚本相关的全部代码

转.air格式所用脚本代码

# export_model.py
import mindspore
import numpy as np
from mindspore import Tensor
from src.deep_learning.networks import NestedUNet


net = NestedUNet(n_channels=3, n_classes=2, is_train=False)
params = mindspore.load_checkpoint('nested_unet_checkpoints/nested_unet_checkpoints.ckpt')
mindspore.load_param_into_net(net, params)
input_tensor = Tensor(np.ones([1, 3, 256, 256]).astype(np.float32))
mindspore.export(net, input_tensor, file_name='nested_unet', file_format='AIR')

转om格式所用命令

atc --framework=1 --model=./nested_unet.air --input_format=NCHW --output=nested_unet --log=error --soc_version=Ascend310B4

报错脚本

import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
import mindspore.dataset as ds

import acl
import acllite_utils as utils
from acllite_model import AclLiteModel
from acllite_resource import resource_list

class AclLiteResource:
    """
    AclLiteResource
    """
    def __init__(self, device_id=0):
        self.device_id = device_id
        self.context = None
        self.stream = None
        self.run_mode = None
        
    def init(self):
        """
        init resource
        """
        print("init resource stage:")
        ret = acl.init()

        ret = acl.rt.set_device(self.device_id)
        utils.check_ret("acl.rt.set_device", ret)

        self.context, ret = acl.rt.create_context(self.device_id)
        utils.check_ret("acl.rt.create_context", ret)

        self.stream, ret = acl.rt.create_stream()
        utils.check_ret("acl.rt.create_stream", ret)

        self.run_mode, ret = acl.rt.get_run_mode()
        utils.check_ret("acl.rt.get_run_mode", ret)

        print("Init resource success")

    def __del__(self):
        print("acl resource release all resource")
        resource_list.destroy()
        if self.stream:
            print("acl resource release stream")
            acl.rt.destroy_stream(self.stream)

        if self.context:
            print("acl resource release context")
            acl.rt.destroy_context(self.context)

        print("Reset acl device ", self.device_id)
        acl.rt.reset_device(self.device_id)
        print("Release acl resource success")

image = cv2.imread('ultrasound_images_to_show/1.jpg')
image = cv2.resize(image, (256, 256))
image = np.expand_dims(image.astype(np.float32).transpose((2, 0, 1)) / 127.5 - 1, axis=0)

acl_resource = AclLiteResource()
acl_resource.init()
path = os.getcwd()
model_path = os.path.join(path, "nested_unet.om")
model = AclLiteModel(model_path)
result = model.execute([image, ])  # result是一个只装了一个numpy数组的列表
output_image = np.argmax(result[0][0], axis=0)
print(output_image.shape)
fig = plt.figure()
plt.imshow(output_image,cmap='gray')
fig.savefig('fig.jpg')

3.根因分析

使用昇腾硬件及om格式模型进行推理时会直接调用acl相关接口进行显存资源的分配,推理完毕后会调用__del__方法将资源释放,若没有实现实例化AclLiteResource并使用init方法初始化资源管理对象,则会产生上述错误。

4.解决方案

在代码:

model = AclLiteModel(model_path)
result = model.execute([image, ])  # result是一个只装了一个numpy数组的列表

的前面补充这两句:

acl_resource = AclLiteResource()
acl_resource.init()

如此操作以后,报错消失,正常运行的控制台输出如下:

推理结果如下: 这正是理想的结果,说明这样操作是正确的。

5.其他说明以及一些注意事项

因此报错相关的issue是本人之前在mindspore的gitee仓提的,故不论是脚本名还是路径名都与样图高度相似。我自己提出的问题我自己发现并解决了,也算一种圆满吧。代码存放的位置是我的gitee仓库,因为本仓库还有其他用途,暂时不能完全开源,因此附件仅包含复现本报错的必要代码。

5.1 注意事项一

使用香橙派的toolkit相关工具将.air模型转.om模型时必须把以下内容加到.bashrc中不然会报错:

# lib libraries that the run package depends on
export LD_LIBRARY_PATH=${LOCAL_ASCEND}/ascend-toolkit/latest/lib64:${LOCAL_ASCEND}/driver/lib64:${LOCAL_ASCEND}/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe/op_tiling:${LD_LIBRARY_PATH}

# Environment variables that must be configured
export TBE_IMPL_PATH=${LOCAL_ASCEND}/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe            # TBE operator implementation tool path
export ASCEND_OPP_PATH=${LOCAL_ASCEND}/ascend-toolkit/latest/opp                                       # OPP path
export PATH=${LOCAL_ASCEND}/ascend-toolkit/latest/compiler/ccec_compiler/bin/:${PATH}                  # TBE operator compilation tool path
export PYTHONPATH=${TBE_IMPL_PATH}:${PYTHONPATH}

以上环境变量并没有内置在香橙派的镜像中,因此需要自己装格式的朋友请将上述内容加到.bashrc中

5.2 注意事项二

从.air转为香橙派可用的模型的转换命令为

atc --framework=1 --model=./nested_unet.air --input_format=NCHW --output=nested_unet --log=error --soc_version=Ascend310B4 # 把“nested_unet”换成待转文件名

注意一定要写Ascend310B4,写Ascend310可能会出问题。
找不到传附件功能,使用超链接下载时生成的下载链接不稳定,代码请命令行下载:
pip install openi后使用如下命令即可下载代码压缩包:

openi dataset download enter/nodule_segmentation shangjing_cell_classification阉割版.zip  --cluster NPU --save_path .

压缩包内包含了复现使用的代码和图像数据。