基于TVM的华为昇腾体系中——
异构计算架构(CANN)是对标英伟达的CUDA + CuDNN的核心软件层,向上支持多种AI框架,向下服务AI处理器,发挥承上启下的关键作用,是提升昇腾AI处理器计算效率的关键平台
主要包括有各种引擎、编译器、执行器、算子库等。
之所以叫异构软件,是因为承载计算的底层硬件包括AI芯片和通用芯片,自然就需要有一层软件来负责算子的调度、加速和执行,最后自动分配到对应的硬件上(CPU或NPU,注:昇腾处理器一般也叫NPU),因此叫异构。
AI框架:
AI框架层主要包括自研框架MindSpore(昇思)和第三方框架(PyTorch、TensorFlow等),其中MindSpore完全由华为自主研发,第三方框架华为只是做了适配和优化,让PyTorch和TensorFlow等框架编写的模型可以高效的跑在昇腾芯片上。
以PyTorch为例,华为的框架研发人员会将其做好适配,然后把适配后的PyTorch源码发布出来,想要在昇腾上用PyTorch的开发者,下载该源码自行编译安装即可。
在安装PyTorch昇腾版后,如果想要把一个开源的PyTorch模型跑起来,只需要对模型源码做简单的适配即可,相关教程可以参考PyTorch训练模型迁移至昇腾完整教程。
对于MindSpore框架,用户直接按照MindSpore官网的教程安装即可,用MindSpore框架编写的模型既可以跑在昇腾上,也支持跑在GPU等其它第三方芯片上。
CANN 3.0如何实现的计算资源智能分配?
神经网络可看作一张张的图,过去大部分图在HostCPU执行,如今昇腾的图编译器,实现了整图下沉,图和算子均可在Device侧执行,减少了芯片与Host CPU的交互时间,从而更充分地发挥昇腾芯片的算力。
像TF搭建的神经网络都是一张张计算图,过去这些图都在HostCPU中执行,资源允许的时候整个图都在HostCPU中执行效率是很高的,但是资源有限的情况就需要Device侧协同处理,也就是昇腾加速卡中,通过把整张图下沉到Device中,可以高效协同CPU完成计算。
根据图的特点和计算资源的分配情况,CANN可以自动进行图的拆分和融合,尽量减少和HostCPU的交互,交互少了,计算资源就能持续保持高强度运转。
数据Pipeline智能优化极大提升了数据资源处理效率,通过人工智能实现数据的自动切分与智能分配流水,以最大化个体计算单元的使用率,从而提高计算效率。
除了图自动编译和图的拆分融合优化,CANN 3.0的1000+算子库让你的神经网络「瞬时」加速。
强如英伟达,cuDNN也只有一百多个算子,CANN 3.0不仅包括了常用的Caffe 及 TF 算子,还独立提供各种加速库,这些加速库可通过 ACL统一编程接口实现,如矩阵乘接口等。
CANN 3.0现在的架构功能十分完善,对外提供适配不同硬件、不同 OS 的驱动,支持GPU+CPU异构通信,对内可实现Stream、内存等底层管理,丰富的加速库支持算子/标量/向量等通用计算,能高效完成图像和视频数据的预处理,执行引擎为深度神经网络计算提供了执行上的保障。
有了CANN 3.0保驾护航,在主流推理场景,昇腾AI推理卡Atlas 300I性能得到大幅提升。
要验证推理性能,多路高清视频分析的场景再合适不过了,高清视频本身流量大,加上多路融合更考验计算平台的并发处理能力,实测表明单张Atlas 300I推理卡可同时处理80路1080p、25FPS的高清视频,是当前市面上同类推理卡路数的2倍。
对交通、安防等场景来说,需要同时处理的视频路数就更多了,少则几百,多则上万,如果单卡能处理更多的任务,规模化应用时成本优势就会扩大,而且硬件数量少了更容易部署。所以很多人工智能厂商,正基于昇腾AI推理卡打造极致性能的高路数视频分析解决方案。
CANN 3.0不仅降低了各个领域使用昇腾芯片开发应用的难度,还提供了很多优秀的中间件和基础库使能各个厂商,但面对谷歌、英伟达、英特尔等国际巨头的强力竞争,想要生存下去,还是要构建一个完整的生态,为学术界和产业界贡献更多算力,为合作伙伴创造更多价值。
import argparse
import numpy as np
import struct
import acl
import os
from PIL import Image
import sys
home_path = get_ipython().getoutput(echo $HOME)
sys.path.append(os.path.join(home_path[0],"jupyter-notebook/"))print(System init success.)from src.acl_dvpp import Dvpp
import src.constants as const
from src.acl_image import AclImage
from src.image_net_classes import get_image_net_class
WORK_DIR = os.getcwd()
ACL_MEM_MALLOC_HUGE_FIRST =0
ACL_MEMCPY_HOST_TO_DEVICE =1
ACL_MEMCPY_DEVICE_TO_HOST =2
ACL_ERROR_NONE =0
MODEL_WIDTH =224
MODEL_HEIGHT =224
IMG_EXT =[.jpg,.JPG,.png,.PNG,.bmp,.BMP,.jpeg,.JPEG]
ret = acl.init()# GLOBAL
load_input_dataset =None
load_output_dataset =None
input_data =[]
output_data =[]
_output_info =[]
images_list =[]
model_desc =0
run_mode =0
INDEX =0if WORK_DIR.find("src")==-1:
MODEL_PATH = WORK_DIR +"/src/model/googlenet_yuv.om"
DATA_PATH = WORK_DIR +"/src/data"else:
MODEL_PATH = WORK_DIR +"/model/googlenet_yuv.om"
DATA_PATH = WORK_DIR +"/data"
buffer_method ="in": acl.mdl.get_input_size_by_index,"out": acl.mdl.get_output_size_by_index
defcheck_ret(message, ret):if ret != ACL_ERROR_NONE:raise Exception(" failed ret=".format(message, ret))definit():
ret = acl.init()
check_ret("acl.init", ret)print("init success")defallocate_res(device_id):
ret = acl.rt.set_device(device_id)
check_ret("acl.rt.set_device", ret)
context, ret = acl.rt.create_context(device_id)
check_ret("acl.rt.create_context", ret)print("allocate_res success")return context
defload_model(model_path):
model_id, ret = acl.mdl.load_from_file(model_path)
check_ret("acl.mdl.load_from_file", ret)print("load_model success")return model_id
defget_model_data(model_id):global model_desc
model_desc = acl.mdl.create_desc()
ret = acl.mdl.get_desc(model_desc, model_id)
check_ret("acl.mdl.get_desc", ret)
input_size = acl.mdl.get_num_inputs(model_desc)
output_size = acl.mdl.get_num_outputs(model_desc)print("get_model_data success")return input_size, output_size
defgen_data_buffer(num, des):global model_desc
func = buffer_method[des]for i inrange(num):#temp_buffer_size = (model_desc, i)
temp_buffer_size = acl.mdl.get_output_size_by_index(model_desc, i)
temp_buffer, ret = acl.rt.malloc(temp_buffer_size,
const.ACL_MEM_MALLOC_NORMAL_ONLY)
check_ret("acl.rt.malloc", ret)if des =="in":
input_data.append("buffer": temp_buffer,"size": temp_buffer_size)elif des =="out":
output_data.append("buffer": temp_buffer,"size": temp_buffer_size)defmalloc_device(input_num, output_num):
gen_data_buffer(input_num, des="in")
gen_data_buffer(output_num, des="out")defimage_process_dvpp(dvpp):global run_mode
global images_list
# _dvpp.init_resource()
IMG_EXT =[.jpg,.JPG,.png,.PNG,.bmp,.BMP,.jpeg,.JPEG]
images_list =[os.path.join(DATA_PATH, img)for img in os.listdir(DATA_PATH)if os.path.splitext(img)[1]in IMG_EXT]
img_list =[]for image_file in images_list:#读入图片
image = AclImage(image_file)
image_input = image.copy_to_dvpp()#对图片预处理
yuv_image = dvpp.jpegd(image_input)
resized_image = dvpp.resize(yuv_image,
MODEL_WIDTH, MODEL_HEIGHT)
img_list.append(resized_image)print("dvpp_process image: success".format(image_file))return img_list
def_data_interaction_in(dataset):global input_data
temp_data_buffer = input_data
for i inrange(len(temp_data_buffer)):
item = temp_data_buffer[i]
ptr = acl.util.numpy_to_ptr(dataset)
ret = acl.rt.memcpy(item["buffer"],
item["size"],
ptr,
item["size"],
ACL_MEMCPY_HOST_TO_DEVICE)
check_ret("acl.rt.memcpy", ret)print("data_interaction_in success")defcreate_buffer(dataset,type="in"):global input_data, output_data
iftype=="in":
temp_dataset = input_data
else:
temp_dataset = output_data
for i inrange(len(temp_dataset)):
item = temp_dataset[i]
data = acl.create_data_buffer(item["buffer"], item["size"])if data isNone:
ret = acl.destroy_data_buffer(dataset)
check_ret("acl.destroy_data_buffer", ret)
_, ret = acl.mdl.add_dataset_buffer(dataset, data)if ret != ACL_ERROR_NONE:
ret = acl.destroy_data_buffer(dataset)
check_ret("acl.destroy_data_buffer", ret)#print("create data_buffer success".format(type))def_gen_dataset(type="in"):global load_input_dataset, load_output_dataset
dataset = acl.mdl.create_dataset()#print("create data_set success".format(type))iftype=="in":
load_input_dataset = dataset
else:
load_output_dataset = dataset
create_buffer(dataset,type)definference(model_id, _input, _output):global load_input_dataset, load_output_dataset
ret = acl.mdl.execute(model_id,
load_input_dataset,
load_output_dataset)
check_ret("acl.mdl.execute", ret)def_destroy_data_set_buffer():global load_input_dataset, load_output_dataset
for dataset in[load_input_dataset, load_output_dataset]:ifnot dataset:continue
num = acl.mdl.get_dataset_num_buffers(dataset)for i inrange(num):
data_buf = acl.mdl.get_dataset_buffer(dataset, i)if data_buf:
ret = acl.destroy_data_buffer(data_buf)
check_ret("acl.destroy_data_buffer", ret)
ret = acl.mdl.destroy_dataset(dataset)
check_ret("acl.mdl.destroy_dataset", ret)def_data_interaction_out(dataset):global output_data
temp_data_buffer = output_data
iflen(dataset)==0:for item in output_data:
temp, ret = acl.rt.malloc_host(item["size"])if ret !=0:raise Exception("cant malloc_host ret=".format(ret))
dataset.append("size": item["size"],"buffer": temp)for i inrange(len(temp_data_buffer)):
item = temp_data_buffer[i]
ptr = dataset[i]["buffer"]
ret = acl.rt.memcpy(ptr,
item["size"],
item["buffer"],
item["size"],
ACL_MEMCPY_DEVICE_TO_HOST)
check_ret("acl.rt.memcpy", ret)defprint_result(result):global images_list, INDEX
dataset =[]for i inrange(len(result)):
temp = result[i]
size = temp["size"]
ptr = temp["buffer"]
data = acl.util.ptr_to_numpy(ptr,(size,),1)
dataset.append(data)
st = struct.unpack("1000f",bytearray(dataset[0]))
vals = np.array(st).flatten()
top_k = vals.argsort()[-1:-6:-1]print()print("======== image: =============".format(images_list[INDEX]))print("======== top5 inference results: =============")
INDEX+=1for n in top_k:
object_class = get_image_net_class(n)print("label:%d confidence: %f, class: %s"%(n, vals[n], object_class))defrelease(model_id, context):global input_data, output_data
ret = acl.mdl.unload(model_id)
check_ret("acl.mdl.unload", ret)while input_data:
item = input_data.pop()
ret = acl.rt.free(item["buffer"])
check_ret("acl.rt.free", ret)while output_data:
item = output_data.pop()
ret = acl.rt.free(item["buffer"])
check_ret("acl.rt.free", ret)if context:
ret = acl.rt.destroy_context(context)
check_ret("acl.rt.destroy_context", ret)
context =None
ret = acl.rt.reset_device(0)
check_ret("acl.rt.reset_device", ret)print(release source success)defmain():global input_data
#init()
context = allocate_res(0)
model_id = load_model(MODEL_PATH)
input_num, output_num = get_model_data(model_id)
malloc_device(input_num, output_num)
dvpp = Dvpp()
img_list = image_process_dvpp(dvpp)for image in img_list:
image_data ="buffer":image.data(),"size":image.size
input_data[0]= image_data
_gen_dataset("in")
_gen_dataset("out")
inference(model_id, load_input_dataset, load_output_dataset)
_destroy_data_set_buffer()
res =[]
_data_interaction_out(res)
print_result(res)
release(model_id,context)if __name__ == __main__:
main()
版权归原作者 Zain Lau 所有, 如有侵权,请联系我们删除。