OpenCV算子开发及其NPU调用方式

OpenCV目前通过调用CANN提供的接口的方式调用NPU,其中调用的接口主要包括数据内存的申请、拷贝和释放、算子执行。

了解CANN

CANN的官方介绍:

CANN(Compute Architecture for Neural Networks)是华为针对AI场景推出的异构计算架构,对上支持多种AI框架,对下服务AI处理器与编程,发挥承上启下的关键作用,是提升昇腾AI处理器计算效率的关键平台。同时针对多样化应用场景,提供高效易用的编程接口,支持用户快速构建基于昇腾平台的AI应用和业务。

image

CANN中面向开发者的即为AscendCL,开发者通过AscendC编程,而CANN则根据编译后的指令通过任务调度将任务下发给不同的处理单元,通过驱动完成对计算资源的调用。这里计算资源主要指AI Core和AI CPU,根据处理数据的不同,即AI Core负责矩阵、向量、标量计算密集的算子计算,而AI CPU则负责非矩阵类、逻辑复杂的分支密集型计算,目前,AI Core还承担了部分无法执行在AI Core的计算密集算子计算。

OpenCV昇腾算子开发

CANN主要的功能特性包括推理应用开发、模型训练和算子开发,OpenCV昇腾算子的开发目前属于推理应用开发,后续提升算子支持完整度过程中会加入自定义算子开发。

开发流程

CANN应用开发基于AscendCL实现,因此应用开发的基础是掌握AscendCL的架构及基本概念和接口的典型调用流程。本篇主要集中于算子调用流程,媒体数据处理的详细解析见dvpp接口调用

image

常用接口

在OpenCV应用开发中,常用的算子包括ACL(去)初始化接口、设备设置接口、device内存操作接口、Stream管理接口和具体的算子接口。ACL(去)初始化接口用来初始化系统内部资源;设备设置接口用来获取device信息、指定或切换device等;device内存操作口用来实现device和host侧的数据搬移;Stream管理接口用来管理任务的并行,一个Stream内部的任务保序执行,即Stream根据发送过来的任务依次执行;不同Stream中的任务并行执行。具体的算子接口则实现具体的计算功能。

下面表格中为除具体算子接口外的常用接口列表,其详细用法参见昇腾文档。

算子类别 接口名称 功能
ACL(去)初始化接口 aclInit(const char *configPath) 初始化ACL系统,用在程序开始时
aclFinalize() 去初始化ACL系统,用在程序退出时
设备设置接口 aclrtGetDevice(int32_t *deviceId) 获取当前线程的目标设备ID
aclrtResetDevice(int32_t deviceId) 重置当前操作的设备并释放设备资源
aclrtGetDeviceCount(uint32_t *count) 获取设备数量
device内存操作接口 aclrtMalloc(void **devPtr,size_t size,aclrtMemMallocPolicy policy) 申请设备内存(真实申请的内存是32bytes对齐的)
aclrtFree(void *devPtr) 释放设备内存
aclrtMemcpy(void *dst, size_t destMax, const void *src,size_t count,aclrtMemcpyKind kind) HOST和DEVICE之间的同步内存复制
aclrtMemcpyAsync(void *dst, size_t destMax,const void *src,size_t count, aclrtMemcpyKind kind, aclrtStream stream) HOST和DEVICE之间的异步内存复制
aclrtMemcpy2d(void *dst,size_t dpitch,const void *src, size_t spitch,size_t width,size_t height,aclrtMemcpyKind kind) HOST和DEVICE之间二维矩阵的同步内存复制
aclrtMemcpy2dAsync(void *dst,size_t dpitch,const void *src, size_t spitch,size_t width,size_t height,aclrtMemcpyKind kind,aclrtStream stream) HOST和DEVICE之间二维矩阵的异步内存复制
aclrtMemset(void *devPtr, size_t maxCount, int32_t value, size_t count) 同步内存初始化
aclrtMemsetAsync(void *devPtr,size_t maxCount,int32_t value, size_t count,aclrtStream stream) 异步内存初始化
Stream管理接口 aclrtCreateStream(aclrtStream *stream) 创建一个Stream
aclrtSynchronizeStream(aclrtStream stream) 阻塞应用程序运行,直到指定Stream中的所有任务都完成

QA

如何确定算子执行在AI Core还是AI CPU?

  1. 查看CANN算子清单
  2. 算子清单由于更新迭代问题不一定最准确,此时可以查看~/Ascend/ascend-toolkit/XXX(CANN版本号)/opp/built-in/op_impl/ai_core/tbe/config/ascendXXX(NPU型号)下的json文件,查看当前设备支持的AI Core算子清单;相应地,AI CPU的则位于/usr/local/Ascend/ascend-toolkit/XXX(CANN版本号)/opp/built-in/op_impl/aicpu/aicpu_kernel/config

如何打印详细日志?

1
2
3
4
5
# 设置全局日志级别(0:DEBUG;1:INFO; 2:WARNING; 3:ERROR; 4NULL(不输出))
- export ASCEND_GLOBAL_LOG_LEVEL=0

# 是否开启日志打屏。开启后,日志将不会保存在log文件中,而是将产生的日志直接打屏显示。
- export ASCEND_SLOG_PRINT_TO_STDOUT=1

参考

  1. 昇腾CANN文档
  2. 昇腾CANN算子开发揭秘

如何部署OpenStack

安装OpenStack

1. 使用oos工具安装

oos(openEuler OpenStack SIG)是OpenStack SIG提供的命令行工具。
安装oos工具,使用纳管的方式部署OpenStack环境,版本22.03-lts-sp2。

若提示无该版本,可在oos工具安装路径(oos/commands/environment/constants.py:OE_OS_RELEASE)添加该版本。该问题已修复,发布版本暂未更新。

  1. 安装oos工具

    pip install openstack-sig-tool

  2. 创建oos环境

    1
    2
    3
    # sshpass在`oos env create`过程中被使用,用于配置对目标主机的免密访问
    dnf install sshpass
    oos env manage -r 22.03-lts-sp2 -i TARGET_MACHINE_IP -p TARGET_MACHINE_PASSWD -n test-oos

    替换TARGET_MACHINE_IP为目标机ip (使用ifconfig查看,如eth0的ip)、TARGET_MACHINE_PASSWD为目标机密码,即登陆当前环境的密码。

  3. 部署OpenStack

    1> 对于禁止密码登陆的机器,需要手动注入公匙
    (oos/etc/key_pair/id_rsa.pub)
    到~/.ssh/authorized_keys中,否则下面的命令会报错

    2> 安装cinder时需要有对应的磁盘/dev/vdb

    3> 其他安装可参考流程/usr/local/etc/oos/playbooks/entry.yaml

    1
    oos env setup test-oos -r wallaby

    安装完毕后可使用如下命令创建虚拟机

    1
    2
    3
    4
    5
    6
    openstack flavor create --disk 1 --vcpus 2 --ram 1024 --id 1 --public my-flavor
    wget http://download.cirros-cloud.net/0.5.2/cirros-0.5.2-aarch64-disk.img -O cirros-0.5.2.img
    openstack image create --disk-format qcow2 --container-format bare --file ./cirros-0.5.2.img --public my-image -c id -f value
    openstack network create --external --share public-network --provider-network-type flat --provider-physical-network provider --default -c id -f value
    openstack subnet create --network public-network --allocation-pool start=10.100.100.189,end=10.100.100.239 --dns-nameserver 100.125.128.250 --gateway 10.100.100.1 --subnet-range 10.100.100.0/24 public-subnet
    openstack server create --flavor my-flavor --image my-image --network public-network --password root my-server
    1
    openstack server list

    创建虚拟机后通过openstack server list命令查询虚拟机信息,回显会打印虚拟机id和ip
    可使用virsh console 或ssh 命令连接虚拟机

2. 使用devstack安装

使用devstack部署OpenStack,干净的环境大概率不会报错

安装步骤如下(master分支)

  1. 安装前准备

    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
    cd /opt/
    git clone https://opendev.org/openstack/devstack.git

    /opt/devstack/tools/create-stack-user.sh
    chown -R stack:stack /opt/devstack
    chmod -R 755 /opt/devstack
    chmod -R 755 /opt/stack

    切换stack用户
    su stack

    确保stack用户的PATH环境变量包含了`/usr/sbin`
    PATH=$PATH:/usr/sbin

    新增配置文件
    vi /opt/devstack/local.conf
    [[local|localrc]]
    DATABASE_PASSWORD=root
    RABBIT_PASSWORD=root
    SERVICE_PASSWORD=root
    ADMIN_PASSWORD=root
    OVN_BUILD_FROM_SOURCE=True

    # arm环境增加如下配置
    [[post-config|$NOVA_CONF]]
    [libvirt]
    cpu_mode=custom
    cpu_model=cortex-a72

    devstack的master分支要求libvirt版本大于7.0
    arm环境安装软件包edk2时缺少arm配置,建议使用下面的yum源安装libvirt和edk2相关软件包
    https://eur.openeuler.openatom.cn/coprs/g/sig-openstack/Libvirt-7.X/repo/openeuler-22.03_LTS/group_sig-openstack-Libvirt-7.X-openeuler-22.03_LTS.repo

  2. 部署OpenStack

    进入/opt/devstack目录,执行./stack.sh,等待部署完成

  3. 日志

    devstack将日志生成到文件需要在部署前在local.conf中添加配置

    未配置日志内容可使用systemd的方法查看日志,如查看nova-compute
    服务的日志,服务名称可在/etc/systemd/system目录下查看,
    其名称携带devstack@前缀,如下图所示

6eb07801786627e341494b0fa34132d

systemd日志查看命令举例如下:
1
journalctl --unit devstack@n-cpu.service
  1. systemd调试方法

    注:退出调试重启systemd服务时,一定要删除断点
    nova-compute调试举例如下:

    1> 在对应的安装目录文件设置断点
    import pdb;pdb.set_trace()

    2> 停止systemd服务
    systemctl stop devstack@n-cpu.service

    3> 执行启动服务
    查看对应服务,在终端1执行该命令

systemd_cmd

4> 调试  
在终端2执行OpenStack创建服务命令,代码会停止在断点处

另外,对于uwsgi这种服务,可能需要加上--honour-stdin才能调试,
可使用uwsgi --help查看参数含义

如何构建一个RPM包

构建一个RPM包

1. rpmdevtools工具及SPEC文件

一些基础点 可以直接从下一章节
网上找了好多相关的教程,RedHat的教程应该是最官方的。
目前没找到如何生成压缩包的,本文使用setuptools生成
还有说使用pyinstaller生成可执行文件然后获取其依赖并压缩的,没有测试这个

Read more

从零开始编译OpenCV NPU教程

从零开始编译OpenCV NPU教程

本文介绍如何从零开始,成功编译OpenCV NPU项目。

本示例使用的机器为华为云昇腾310虚拟机。

1
2
3
实例类型:AI加速型Ai1s
操作系统:Ubuntu 18.04
IDE:VSCode
Read more

OpenCV社区洞察

OpenCV背景

OpenCV是1998年在Intel公司内的CVL(计算机视觉库)项目,由Gary Bradski发起,并由Vadim Pisarevsky担任技术主管,于1999年开源,2000年首次公开发布。2008年OpenCV的核心成员加入Willow GarageItseez公司继续开发。Itseez公司在2016年被Intel收购,核心开发团队重回Intel。

目前主要由Intel公司赞助OpenCV核心开发团队,并且很多OpenCV的开发者是Intel的雇员。这是一个由Intel公司主导,OpenCV.org非盈利基金会运营的开源项目。2019年以来,核心开发团队由Intel,OpenCV中国团队和xperience.ai公司组成。

Read more

EulerPublisher: 一键发布openEuler镜像背后的技术

作者:@wjunLu

1. EulerPublisher架构

eulerpublisher作为一款openEuler“一键式”发布工具,提供openEuler容器镜像、云镜像、WSL等镜像定制、发布和测试的能力。本项目主要使用python语言实现,并且以CLI的方式提供给用户使用。

eulerpublisher按照使用场景,分为容器镜像(container)、云镜像(cloudimg)、WSL(wsl)这几个模块,而每个模块又按照子场景划分不同的子功能模块,每个子场景功能模块具备prepare、build、publish、check等能力,因而形成一种按照主场景子场景、以及对应动作构成的分层软件架构,如图所示:
无标题-2023-08-14-0928-3

Read more