华为AI战略的CANN

news2024/11/24 15:29:03

在这里插入图片描述

基于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 = 0

if 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
    

def check_ret(message, ret):
    if ret != ACL_ERROR_NONE:
        raise Exception(" failed ret="
                        .format(message, ret))
def init():
    ret = acl.init()
    check_ret("acl.init", ret)
    print("init success")
def allocate_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
def load_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

def get_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

def gen_data_buffer(num, des):
    global model_desc
    func = buffer_method[des]
    for i in range(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)
def malloc_device(input_num, output_num):
    gen_data_buffer(input_num, des="in")
    gen_data_buffer(output_num, des="out")
def image_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 in range(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")

def create_buffer(dataset, type="in"):
    global input_data, output_data
    if type == "in":    
        temp_dataset = input_data
    else:
        temp_dataset = output_data
    for i in range(len(temp_dataset)):
        item = temp_dataset[i]
        data = acl.create_data_buffer(item["buffer"], item["size"])
        if data is None:
            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))
    if type == "in":    
        load_input_dataset = dataset
    else:
        load_output_dataset = dataset
    create_buffer(dataset, type)

def inference(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]:
        if not dataset:
            continue
        num = acl.mdl.get_dataset_num_buffers(dataset)
        for i in range(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
    if len(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 in range(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)

def print_result(result):
    global images_list, INDEX
    dataset = []
    for i in range(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+=1
    for n in top_k:
        object_class = get_image_net_class(n)
        print("label:%d  confidence: %f, class: %s" % (n, vals[n], object_class))

def release(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)
def main():
    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()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/880294.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java SpringBoot Vue ERP系统

系统介绍 该ERP系统基于SpringBoot框架和SaaS模式,支持多租户,专注进销存财务生产功能。主要模块有零售管理、采购管理、销售管理、仓库管理、财务管理、报表查询、系统管理等。支持预付款、收入支出、仓库调拨、组装拆卸、订单等特色功能。拥有商品库存…

【网络基础】应用层协议

【网络基础】应用层协议 文章目录 【网络基础】应用层协议1、协议作用1.1 应用层需求1.2 协议分类 2、HTTP & HTTPS2.1 HTTP/HTTPS 简介2.2 HTTP工作原理2.3 HTTPS工作原理2.4 区别 3、URL3.1 编码解码3.2 URI & URL 4、HTTP 消息结构4.1 HTTP请求方法4.2 HTTP请求头信…

虹科干货 | 化身向量数据库的Redis Enterprise——快速、准确、高效的非结构化数据解决方案!

用户期望在他们遇到的每一个应用程序和网站都有搜索功能。然而,超过80%的商业数据是非结构化的,以文本、图像、音频、视频或其他格式存储。Redis Enterprise如何实现矢量相似性搜索呢?答案是,将AI驱动的搜索功能集成到Redis Enter…

聊聊计算机技术

目录 1.计算机的概念 2.计算机的发展过程 3.计算机的作用 4.计算机给人类带来的福利 1.计算机的概念 计算机是一种用于处理和存储数据的电子设备。它能够执行各种操作,比如计算、逻辑操作、数据存储和检索等。计算机由硬件和软件两部分组成。 计算机的硬件包括中…

SAP ABAP 直接把内表转换成PDF格式(smartform的打印函数输出OTF格式数据)

直接上代码: REPORT zcycle055.DATA: lt_tab TYPE TABLE OF zpps001. DATA: ls_tab TYPE zpps001.ls_tab-werks 1001. ls_tab-gamng 150.00. ls_tab-gstrp 20201202. ls_tab-aufnr 000010000246. ls_tab-auart 标准生产. ls_tab-gltrp 20201205. ls_tab-matn…

【史上最全】计算机的编年史

前几天我写算力简史的时候,顺便整理了一份计算机技术的编年史(将近一万字)。今天发给大家,以供参考。 1614年苏格兰人约翰纳皮尔(John Napier)发表了一篇论文,其中提到他发明了一种可以计算四则…

【JavaEE进阶】SpringBoot 日志

文章目录 一. 日志有什么用?二. 自定义日志打印1. 日志的使用与打印 三. 日志级别1. 日志级别有什么用?2. 日志级别的分类及使用 四. 日志持久化五. 更简单的日志输出---Lombok1. Lombok的使用2. lombok原理解释2.1 Lombok更多注解说明 一. 日志有什么用? 在Java中&#xf…

企业做直播时如何选择适合自己的直播平台?

企业做直播时如何选择适合自己的直播平台? 可以通过对比不同直播平台的技术能力、服务质量、安全性等方面的内容,选择最适合自己的直播平台。 企业做直播如何选择直播平台 我的文章推荐: [视频图文] 线上研讨会是什么,企业对内对…

python3装饰器理解与实战

前言 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任务代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装…

Kubuesphere部署Ruoyi:持久化存储配置

按照如下教程配置NFS 先服务器&#xff1a;搭建 NFS 服务器 后客户端&#xff1a;安装 NFS Client 按照链接操作以后&#xff0c;在客户端上面把目录挂载到服务端 rootclient_banana:/# mount 172.25.110.41:/mnt/nfs_share /mnt/client_floder 客户端: mount <server-ip…

微服务系列文章之 Springboot+Vue实现登录注册

一、springBoot 创建springBoot项目 分为三个包&#xff0c;分别为controller&#xff0c;service&#xff0c; dao以及resource目录下的xml文件。 UserController.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 …

代理模式概述

1.代理模式概述 学习内容 1&#xff09;概述 为什么要有 “代理” &#xff1f; 生活中就有很多例子&#xff0c;比如委托业务&#xff0c;黄牛&#xff08;票贩子&#xff09;等等代理就是被代理者没有能力或者不愿意去完成某件事情&#xff0c;需要找个人代替自己去完成这…

地理数据的双重呈现:GIS与数据可视化

前一篇文章带大家了解了GIS与三维GIS的关系&#xff0c;本文就GIS话题带大家一起探讨一下GIS和数据可视化之间的关系。 GIS&#xff08;地理信息系统&#xff09;和数据可视化在地理信息科学领域扮演着重要的角色&#xff0c;它们之间密切相关且相互增强。GIS是一种用于采集、…

算法:深度优先遍历

文章目录 什么是深搜典型题目积累 本篇主要积累的是深度优先遍历算法 什么是深搜 深度优先搜索英文缩写为 DFS 即Depth First Search 其过程是对每一个可能的分支路径深入到不能再深入为止&#xff0c;而且每个节点只能访问一次 简单来说就是: 一路走到头&#xff0c;不撞墙…

ESD实时监测报警系统的主要功能

ESD&#xff08;Electrostatic Discharge&#xff09;实时监测报警系统是一种用于检测和预防静电放电的系统。静电放电是指在两个或多个物体之间由于电荷失衡而引起的突然放电现象&#xff0c;可能会对电子设备、化学品等敏感物体造成损害。 ESD实时监测报警系统的主要功能是通…

冠达管理:价格破发是什么意思啊?

价格破发是股票商场中一个比较常见的术语&#xff0c;也是常常让出资者感到困惑的现象之一。价格破发是指新股发行后&#xff0c;由于各种原因&#xff0c;股票价格低于发行价的现象。那么&#xff0c;价格破发的原因是什么呢&#xff1f;价格破发与出资者有哪些联系呢&#xf…

Stephen Wolfram:那么…ChatGPT 在做什么,为什么它有效呢?

So … What Is ChatGPT Doing, and Why Does It Work? 那么…ChatGPT在做什么&#xff0c;为什么它有效呢&#xff1f; The basic concept of ChatGPT is at some level rather simple. Start from a huge sample of human-created text from the web, books, etc. Then train…

ChatGPT写论文不靠谱?但可处理简单任务如编写摘要或生成代码

日前&#xff0c;一项题为《水果蔬菜消费和体力活动对成年人糖尿病风险的影响》的学术研究论文发布。乍一看&#xff0c;这似乎是在学术期刊上又发表的一个调查。然而这篇论文并不常见&#xff0c;因为它是在ChatGPT的帮助下只用了不到一个小时的时间完成的。[1] 本文包括摘要…

护眼灯值不值得买?什么护眼灯对眼睛好

想要选好护眼台灯首先我们要知道什么是护眼台灯&#xff0c;大的方向来看&#xff0c;护眼台灯就是可以保护视力的台灯&#xff0c;深入些讲就是具备让灯发出接近自然光特性的光线&#xff0c;同时光线不会伤害人眼而出现造成眼部不适甚至是视力降低的照明设备。 从细节上看就…

日常BUG——代码提交到了本地但是没有push,删除了本地分支如何恢复

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;日常BUG、BUG、问题分析☀️每日 一言 &#xff1a;存在错误说明你在进步&#xff01; 一、问题描述 代码在本地提交了&#xff0c;但是没有push到远程&#xff0c;然后删除了本地的分支。想要恢…