昇腾 - 快速理解AscendCL(Ascend Computing Language)基础概念的HelloWord
flyfish
AscendCL(Ascend Computing Language)是一套用于在昇腾平台上开发深度神经网络应用的C语言API库,提供运行资源管理、内存管理、模型加载与执行、算子加载与执行、媒体数据处理等API,能够实现利用昇腾硬件计算资源、在昇腾CANN平台上进行深度学习推理计算、图形图像预处理、单算子加速计算等能力。
目录结构
源码
#include <iostream>
#include "acl/acl.h"
# define INFO_LOG(fmt, args...) fprintf(stdout, "[INFO] " fmt "\n", ##args)
# define WARN_LOG(fmt, args...) fprintf(stdout, "[WARN] " fmt "\n", ##args)
# define ERROR_LOG(fmt, args...) fprintf(stdout, "[ERROR] " fmt "\n", ##args)
using namespace std;
int main(int argc, char *argv[])
{
uint32_t deviceId = 0;
aclrtContext context = nullptr;
aclrtStream stream = nullptr;
const char *aclConfigPath = "acl.json";
aclError ret = aclInit(aclConfigPath);
if (ret != ACL_ERROR_NONE){
ERROR_LOG("Acl Init Failed");
return 1;
}
INFO_LOG("Acl Init Success");
ret = aclrtSetDevice(deviceId);
if (ret != ACL_ERROR_NONE){
ERROR_LOG("Acl Set Device Failed");
return 1;
}
INFO_LOG( "Acl Set Device Success,Current DeviceID:%d", deviceId);
ret = aclrtCreateContext(&context, deviceId);
if (ret != ACL_ERROR_NONE){
ERROR_LOG("Acl Create Context Failed");
return 1;
}
INFO_LOG("Acl Create Context Success");
ret = aclrtCreateStream(&stream);
if (ret != ACL_ERROR_NONE){
ERROR_LOG("Acl Create Stream Failed");
return 1;
}
INFO_LOG("Acl Create Stream Success");
/*
* 业务执行
*/
ret = aclrtDestroyStream(stream);
if (ret != ACL_ERROR_NONE){
ERROR_LOG("Acl Destroy Stream Failed");
return 1;
}
INFO_LOG("Acl Destroy Stream Success");
ret = aclrtDestroyContext(context);
if (ret != ACL_ERROR_NONE){
ERROR_LOG("Acl Destroy Context Failed");
return 1;
}
INFO_LOG("Acl Destroy Context success");
ret = aclrtResetDevice(deviceId);
if (ret != ACL_ERROR_NONE){
ERROR_LOG("Acl Reset Device Failed");
return 1;
}
INFO_LOG("Acl Reset Device Success");
ret = aclFinalize();
if (ret != ACL_ERROR_NONE){
ERROR_LOG("Acl Finalize Failed");
return 1;
}
INFO_LOG("Acl Finalize Success");
return 0;
}
与源码所在位置是相同目录的cmakelist.txt
cmake_minimum_required(VERSION 3.5.1)
project(ACLHelloWorld)
add_compile_options(-std=c++11)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../../../out")
set(CMAKE_CXX_FLAGS_DEBUG "-fPIC -O0 -g -Wall")
set(CMAKE_CXX_FLAGS_RELEASE "-fPIC -O2 -Wall")
set(INC_PATH $ENV{DDK_PATH})
if (NOT DEFINED ENV{DDK_PATH})
set(INC_PATH "/usr/local/Ascend/ascend-toolkit/latest")
message(STATUS "set default INC_PATH: ${INC_PATH}")
else()
message(STATUS "set INC_PATH: ${INC_PATH}")
endif ()
set(LIB_PATH $ENV{NPU_HOST_LIB})
if (NOT DEFINED ENV{NPU_HOST_LIB})
set(LIB_PATH "/usr/local/Ascend/ascend-toolkit/lastest/runtime/lib64/stub")
message(STATUS "set default LIB_PATH: ${LIB_PATH}")
else()
message(STATUS "set LIB_PATH: ${LIB_PATH}")
endif ()
include_directories(
${INC_PATH}/runtime/include/
)
link_directories(
${LIB_PATH}
)
add_executable(main
main.cpp)
target_link_libraries(main ascendcl stdc++)
外层cmakelist.txt
cmake_minimum_required(VERSION 3.5.1)
# project information
project(untitled2)
include(set_env.cmake)
set(MX_SDK_HOME $ENV{MX_SDK_HOME})
if (NOT DEFINED ENV{MX_SDK_HOME})
set(MX_SDK_HOME "/usr/local/Ascend/mindx_sdk")
message(STATUS "set default MX_SDK_HOME: ${MX_SDK_HOME}")
else ()
message(STATUS "env MX_SDK_HOME: ${MX_SDK_HOME}")
endif()
add_subdirectory("./src")
set_env.cmake
# This file is used to configure DDK-related environment variables.
# It is generated or updated in the following two scenarios:
# 1. This file does not exist or does not contain "ENV{DDK_PATH}".
# 2. The CANN version has been changed.
if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux")
set(ENV{DDK_PATH} /usr/local/Ascend/ascend-toolkit/7.0.0)
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpmachine OUTPUT_VARIABLE arch)
string(FIND ${arch} "x86" res)
if(NOT ${res} MATCHES "-1")
set(ENV{NPU_HOST_LIB} /usr/local/Ascend/ascend-toolkit/7.0.0/x86_64-linux/runtime/lib64/stub)
else()
set(ENV{NPU_HOST_LIB} /usr/local/Ascend/ascend-toolkit/7.0.0/aarch64-linux/runtime/lib64/stub)
endif()
set(ENV{MX_SDK_HOME} /usr/local/Ascend/mxVision-5.0.RC3)
else()
if (NOT EXISTS "C:/Program Files/HuaWei/Ascend")
set(ENV{DDK_PATH} C:/Users/bobod/.mindstudio/huawei/adk/remote/7.0.0)
endif()
endif()
编译结果输出
(base) root@orangepiaipro:~/MindStudio-WorkSpace/untitled2_731bdeb2/out# ./main
[INFO] Acl Init Success
[INFO] Acl Set Device Success,Current DeviceID:0
[INFO] Acl Create Context Success
[INFO] Acl Create Stream Success
[INFO] Acl Destroy Stream Success
[INFO] Acl Destroy Context success
[INFO] Acl Reset Device Success
[INFO] Acl Finalize Success
Device
Device就是用来计算的硬件设备。第一次用 aclrtSetDevice 这个接口把设备指定好之后,设备就“上线了”。
每次用 aclrtSetDevice 选这个设备,系统会给它加1个“使用次数”;当用 aclrtResetDevice 把设备“重置”时,系统就减1个“使用次数”。
当“使用次数”变成0时,这个设备在当前程序里就不能用了。
Context
Context是一个执行环境,所有操作都在这个环境里运行。它是和一个设备绑定的,不能在多个设备间共用。
有两种方式可以创建Context:一种是系统自动创建,这叫隐式创建;另一种是自己手动创建,这叫显式创建。
隐式创建的Context(默认的),在用 aclrtSetDevice 选定设备时就会自动生成。当用 aclrtResetDevice 把设备“重置”到0次时,Context也会自动消失。系统只会创建一个隐式的Context,后面再用 aclrtSetDevice 选同一个设备,只是增加这个默认Context的“使用次数”。
显式创建的Context,得自己用 aclrtCreateContext 创建,然后再用 aclrtDestroyContext 销毁它。
如果在一个程序里创建了多个Context,那每次只能在一个Context里工作。建议明确指定当前线程要用哪个Context,这样代码维护起来更方便。
Stream
Stream就是设备上的“执行管道”,它能保证任务按照写的顺序一个接一个地执行。
和Context一样,Stream也分为隐式和显式两种创建方式。
每个Context都会有一个默认的Stream,这个Stream是系统自动创建的,生命周期和它归属的Context一样长。
也可以显式地创建多个Stream,用 aclrtCreateStream 创建,用 aclrtDestroyStream 销毁。显式创建的Stream是和某个Context绑定的,当这个Context被销毁后,Stream虽然还在,但已经不能用了。