diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/attr_value.h b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/attr_value.h new file mode 100644 index 0000000000000000000000000000000000000000..bebb0eaaf4a5e7abc39639ee2fbf473e539a3f74 --- /dev/null +++ b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/attr_value.h @@ -0,0 +1,110 @@ +/** + * Copyright (C) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * Description: + */ + +#ifndef FLOW_FUNC_ATTR_VALUE_H +#define FLOW_FUNC_ATTR_VALUE_H + +#include +#include +#include +#include "flow_func_defines.h" +#include "data_type.h" + +namespace FlowFunc { +class FLOW_FUNC_VISIBILITY AttrValue { +public: + AttrValue() = default; + + virtual ~AttrValue() = default; + + AttrValue(const AttrValue &) = delete; + + AttrValue(AttrValue &&) = delete; + + AttrValue &operator=(const AttrValue &) = delete; + + AttrValue &operator=(AttrValue &&) = delete; + + /* + * get string value of attr. + * @para value: string value of attr + * @return 0:SUCCESS, other:failed + */ + virtual int32_t GetVal(std::string &value) const = 0; + + /* + * get string list value of attr. + * @param value: string list value of attr + * @return 0:SUCCESS, other:failed + */ + virtual int32_t GetVal(std::vector &value) const = 0; + + /* + * get int value of attr. + * @param value: int value of attr + * @return 0:SUCCESS, other:failed + */ + virtual int32_t GetVal(int64_t &value) const = 0; + + /* + * get int list value of attr. + * @param value: int list value of attr + * @return 0:SUCCESS, other:failed + */ + virtual int32_t GetVal(std::vector &value) const = 0; + + /* + * get int list list value of attr. + * @param value: int list list value of attr + * @return 0:SUCCESS, other:failed + */ + virtual int32_t GetVal(std::vector> &value) const = 0; + + /* + * get float value of attr. + * @param value: float value of attr + * @return 0:SUCCESS, other:failed + */ + virtual int32_t GetVal(float &value) const = 0; + + /* + * get float list value of attr. + * @param value: float list value of attr + * @return 0:SUCCESS, other:failed + */ + virtual int32_t GetVal(std::vector &value) const = 0; + + /* + * get bool value of attr. + * @param value: bool value of attr + * @return 0:SUCCESS, other:failed + */ + virtual int32_t GetVal(bool &value) const = 0; + + /* + * get bool list value of attr. + * @param value: bool list value of attr + * @return 0:SUCCESS, other:failed + */ + virtual int32_t GetVal(std::vector &value) const = 0; + + /* + * get data type value of attr. + * @param value: data type value of attr + * @return 0:SUCCESS, other:failed + */ + virtual int32_t GetVal(DataType &value) const = 0; + + /* + * get data type list value of attr. + * @param value: data type list value of attr + * @return 0:SUCCESS, other:failed + */ + virtual int32_t GetVal(std::vector &value) const = 0; +}; +} + +#endif // FLOW_FUNC_ATTR_VALUE_H + diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/data_types.h b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/data_types.h new file mode 100644 index 0000000000000000000000000000000000000000..2a0e2295c3afce01e7d57e437f46bec0dca26609 --- /dev/null +++ b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/data_types.h @@ -0,0 +1,41 @@ +/** + * Copyright (C) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * Description: + */ + +#ifndef FLOW_FUNC_DATA_TYPE_H +#define FLOW_FUNC_DATA_TYPE_H + +#include + +namespace FlowFunc { +enum class DataType : int32_t { + DT_FLOAT = 0, // float type + DT_FLOAT16 = 1, // fp16 type + DT_INT8 = 2, // int8 type + DT_INT16 = 6, // int16 type + DT_UINT16 = 7, // uint16 type + DT_UINT8= 4, // uint8 type + DT_INT32 = 3, // int32 type + DT_INT64 = 9, // int64 type + DT_UINT32 = 8, // unsigned int32 + DT_UINT64 = 10, // unsigned int64 + DT_BOOL = 12, // bool type + DT_DOUBLE = 11, // double type + + DT_QINT8 = 18, // qint8 type + DT_QINT16 =19, // qint16 type + DT_QINT32 = 20, // qint32 type + DT_QUINT8 = 21, // quint8 type + DT_QUINT16 = 22, // quint16 type + + DT_DUAL = 25, // dual output type + DT_INT4 = 29, // int4 type + DT_UINT1 = 30, // uint1 type + DT_INT2 = 31, // int2 type + DT_UINT2 = 32, // uint2 type + DT_UNDEFINED // Used to indicate a DataType fieldhas not been set. +}; +} // namespace FlowFunc + +#endif // FLOW_FUNC_DATA_TYPE_H \ No newline at end of file diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/flow_func_defines.h b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/flow_func_defines.h new file mode 100644 index 0000000000000000000000000000000000000000..6daab63df65dfd931666e71d2e4d279373fcdfa4 --- /dev/null +++ b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/flow_func_defines.h @@ -0,0 +1,28 @@ +/** + * Copyright (C) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * Description: + */ + +#ifndef FLOW_FUNC_DEFINES_H +#define FLOW_FUNC_DEFINES_H +#include + +#define FLOW_FUNC_VISIBILITY __attribute__((visibility("default"))) + +namespace FlowFunc { +// common error code +constexpr int32_t FLOW_FUNC_SUCCESS = 0x0000; // Success code +constexpr int32_t FLOW_FUNC_FAILED = 0x0001; // Failed code +constexpr int32_t FLOW_FUNC_ERR_PARAM_INVALID = 0x0002; // parem invalid + +// attr error code +constexpr int32_t FLOW_FUNC_ERR_ATTR_NOT_EXITS = 0x0101; // attr is not exists +constexpr int32_t FLOW_FUNC_ERR_ATTR_TYPE_MISMATCH = 0x0102; // attr type is mismatch + +// Drv error code +constexpr int32_t FLOW_FUNC_ERR_DRV_ERROR = 0x0201; // driver error +constexpr int32_t FLOW_FUNC_ERR_QUEUE_ERROR = 0x0202; // queue error +constexpr int32_t FLOW_FUNC_ERR_MBUF_ERROR = 0x0203; // mbuf error +} + +#endif // FLOW_FUNC_DEFINES_H \ No newline at end of file diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/meta_context.h b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/meta_context.h new file mode 100644 index 0000000000000000000000000000000000000000..a68672c2e4a30a5b54d2e74f0c3264e17b42fcde --- /dev/null +++ b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/meta_context.h @@ -0,0 +1,57 @@ +/** + * Copyright (C) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * Description: + */ + +#ifndef FLOW_FUNC_META_CONTEXT_H +#define FLOW_FUNC_META_CONTEXT_H + +#include +#include +#include "flow_func_defines.h" +#include "attr_value.h" +#include "tensor.h" + +namespace FlowFunc { +class FLOW_FUNC_VISIBILITY MetaContext { +public: + MetaContext() = default; + + virtual ~MetaContext() = default; + + /** + * @brief alloc tensor by shape and data type. + * @param shape: tensor shape + * @param dataType: data type + * @return tensor + */ + virtual std::shared_ptr AllocTensor(const std::vector &shape, DataType dataType) = 0; + + /** + * @brief set output tensor. + * @param outIdx: output index, start from 0. + * @param outTensor: output tensor + * @return 0:success, other:failed. + */ + virtual int32_t SetOutput(uint32_t outIdx, std::shared_ptr outTensor) = 0; + + /** + * @brief get attr. + * @param name: attr name. + * @return AttrValue *: not null->success, null->failed. + */ + virtual std::shared_ptr GetAttr(const std::string &name) const = 0; + + template + int32_t GetAttr(const std::string &name, T &value) const + { + auto attrValue = GetAttr(name); + if (attrValue == nullptr) { + return FLOW_FUNC_ERR_ATTR_NOT_EXITS; + } + return attrValue->GetVal(value); + } +}; +} + +#endif // FLOW_FUNC_META_CONTEXT_H \ No newline at end of file diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/meta_flow_func.h b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/meta_flow_func.h new file mode 100644 index 0000000000000000000000000000000000000000..7f5b406c01f161ff13fa83ab7d0eb8db8cee5490 --- /dev/null +++ b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/meta_flow_func.h @@ -0,0 +1,67 @@ +/** + * Copyright (C) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * Description: + */ +#ifndef META_FLOW_FUNC_H +#define META_FLOW_FUNC_H + +#include +#include +#include +#include "flow_func_defines.h" +#include "tensor.h" +#include "meta_context.h" + +namespace FlowFunc { +class FLOW_FUNC_VISIBILITY MetaFlowFunc { +public: + MetaFlowFunc() = default; + + virtual ~MetaFlowFunc() = default; + + /** + * set context. + * it will be call before Init. + * @param metaContext context. + */ + void SetContext(MetaContext *metaContext) + { + context_ = metaContext; + } + + /** + * @brief Flow func init. + * only call once. + * @return 0:success, other: failed. + */ + virtual int32_t Init() = 0; + + /** + * @brief flow func proc func. + * @param inputTensors: input tensors + * @return 0:success, other: failed. + * If an unrecoverable exception occurs, return error. + * others can call SetRetCode to out tensor, than return success. + * if return success, schedule will be break. + */ + virtual int32_t Proc(const std::vector> &inputTensors) = 0; + +protected: + MetaContext *context_ = nullptr; +}; + +using FLOW_FUNC_CREATOR_FUNC = std::function(void)>; + +FLOW_FUNC_VISIBILITY bool RegisterFlowFunc(const std::string &flowFuncName, const FLOW_FUNC_CREATOR_FUNC &func); + +#define REGISTER_FLOW_FUNC_IMPL(name, ctr, clazz) \ +std::shared_ptr Creator_##clazz##ctr##_FlowFunc() \ +{ \ + return std::make_shared(); \ +} \ +bool g_##clazz##ctr##_FlowFuncCreator __attribute__((unused)) = RegisterFlowFunc(name, Creator_##clazz##ctr##_FlowFunc) + +#define REGISTER_FLOW_FUNC(name, clazz) REGISTER_FLOW_FUNC_IMPL(name, __COUNTER__, clazz) +} +#endif //META_FLOW_FUNC_H + diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/tensor.h b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/tensor.h new file mode 100644 index 0000000000000000000000000000000000000000..a3bf3d4a7059fbf70faf712d03652b045dfdce03 --- /dev/null +++ b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/inc/tensor.h @@ -0,0 +1,34 @@ +/** + * Copyright (C) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * Description: + */ +#ifndef FLOW_FUNC_TENSOR_H +#define FLOW_FUNC_TENSOR_H + +#include +#include +#include "flow_func_defines.h" +#include "data_type.h" + +namespace FlowFunc { +class FLOW_FUNC_VISIBILITY Tensor { +public: + Tensor() = default; + + virtual ~Tensor() = default; + + virtual const std::vector &GetShape() const = 0; + + virtual DataType GetDataType() const = 0; + + virtual void *GetData() const = 0; + + virtual uint64_t GetDataSize() const = 0; + + virtual int32_t GetRetCode() const = 0; + + virtual void SetRetCode(int32_t retCode) = 0; +}; +} + +#endif // FLOW_FUNC_TENSOR_H diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/lib/x86_64/libflow_func.so b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/lib/x86_64/libflow_func.so new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/readme.md b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..7ce49b37f985ea1bf2302372500b9a6de4e88534 --- /dev/null +++ b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/readme.md @@ -0,0 +1,147 @@ +# 样例使用指导 + +## 功能描述 + +本样例为IR模型构建样例,支持通过以下几种方式构建Graph,并生成适配昇腾AI处理器的离线模型,用户可任选其一。 + +- 通过算子原型构建Graph +- 将TensorFlow原始模型解析为Graph +- 将Caffe原始模型解析为Graph + +## 目录结构 + +``` +├── src +│ ├──main.cpp //实现文件 +├── Makefile //编译脚本 +├── CMakeLists.txt //编译脚本 +├── data +│ ├──data_generate.py // 通过算子原型构建Graph时,用于生成Graph所需要的数据信息,例如权重、偏置等数据 +│ ├──tensorflow_generate.py // 将TensorFlow原始模型解析为Graph时,用于生成.pb格式的TensorFlow模型 +│ ├──caffe_generate.py // 将Caffe原始模型解析为Graph时,用于生成.pbtxt格式的Caffe模型与.caffemodel格式的权重文件 +├── scripts +│ ├──host_version.conf +│ ├──testcase_300.sh +``` + +## 环境要求 + +- 操作系统及架构:CentOS x86系统、CentOS aarch64系统、Euleros x86系统、Euleros aarch64系统 +- 编译器:g++ +- 芯片:all +- python及依赖的库:python3.7.5 +- 已完成昇腾AI软件栈在开发环境上的部署 +- 如果采用模型解析方式构图,请在当前环境安装tensorflow1.15.0和caffe + +## 准备构图数据 + +- 如果用户需要通过算子原型构建Graph,请执行以下操作准备构图数据: + 1. 在**data**目录执行数据生成脚本,**python3.7.5 data_generate.py** + 2. 执行结束后,在**data**目录下生成.bin格式的数据。后续模型构建时会从该文件读取权重、偏置等数据。 + +- 如果用户需要将TensorFlow原始模型解析为Graph,请执行以下操作准备构图数据: + 1. 在**data**目录执行tensorflow原始模型生成脚本,**python3.7.5 tensorflow_generate.py** + 2. 执行结束后,在**data**目录下生成.pb格式的模型文件。后续将原始模型解析时会使用该tensorflow模型,名称为tf_test.pb。 + +- 如果用户需要将Caffe原始模型解析为Graph,请执行以下操作准备构图数据: + 1. 在**data**目录执行caffe原始模型生成脚本,**python3.7.5 caffe_generate.py** + 2. 执行结束后,在**data**目录下生成.pbtxt格式的模型文件与.caffemodel格式的权重文件。后续将caffe原始模型与权重文件解析时会使用两者,名称分别为caffe_test.pbtxt与caffe_test.caffemodel。 + + +## 程序编译 + +1. 根据实际情况修改**Makefile**文件中的如下信息。 + + - ASCEND_PATH:指定到ATC或FwkACLlib的安装目录,例如/home/HwHiAiUser/Ascend/ascend-toolkit/latest + + - INCLUDES:需要包含的头文件,对于本示例,无需修改。如果是用户自行开发的代码,当需要添加头文件时,在示例下方直接增加行即可,注意不要删除原有项目。如果网络中有自定义算子,请增加自定义算子的原型定义头文文件。 + + - LIBS:需要链接的库,对于本示例,无需修改。如果是用户自行开发的代码,当需要添加链接库时,在示例下方直接增加行即可,注意不要删除原有项目。 + + >禁止链接软件包中的其他so,否则后续升级可能会导致兼容性问题。 + +2. 执行如下命令进行编译。 + + 如果安装的是ATC组件,依次执行**make clean**和**make ir_build**。 + + 如果安装的是FwkACLlib组件,依次执行**make clean**和**make fwk_ir_build**。 + +3. 编译结束后,在**out**目录下生成可执行文件**ir_build**或者**fwk_ir_build。** + +## 程序运行 + +1. 配置环境变量。 + + - 若运行环境上安装的“Ascend-cann-toolkit”包,环境变量设置如下: + + ``` + . ${HOME}/Ascend/ascend-toolkit/set_env.sh + ``` + + - 若运行环境上安装的“Ascend-cann-nnrt”包,环境变量设置如下: + + ``` + . ${HOME}/Ascend/nnrt/set_env.sh + ``` + + - 若运行环境上安装的“Ascend-cann-nnae”包,环境变量设置如下: + + ``` + . ${HOME}/Ascend/nnae/set_env.sh + ``` + + “$HOME/Ascend”请替换相关软件包的实际安装路径。 + + +2. 在**out**目录下执行可执行文件。 + + - 如果用户采用算子原型构图方式,请执行如下命令: + + 如果安装了ATC组件,请执行:**./ir_build ${soc_version} gen** + + 如果安装了FwkACLlib组件,请执行:**./fwk_ir_build ${soc_version} gen** + + ${soc_version}:昇腾AI处理器的版本,可以从ATC或FwkACLlib安装路径下的/data/platform_config查看ini文件名,文件名即为对应版本,如果仍然无法确定具体使用的版本号,可以通过如下方法查询: + 1. 单击如下手册中的链接并进入该手册,[CANN Ascend-DMI工具用户指南](https://support.huawei.com/enterprise/zh/ascend-computing/atlas-data-center-solution-pid-251167910?category=operation-maintenance)。 + 2. 完成“使用工具>使用前准备“,然后进入“使用工具>设备实时状态查询“章节。 + 3. 使用相关命令查看芯片的详细信息,例如使用**ascend-dmi -i -dt**命令查看芯片的详细信息,返回信息中“Chip Name“对应取值,去除空格后,即为具体使用的${soc_version}。 + + 编译成功提示: + + ``` + ========== Generate Graph1 Success!========== + Build Model1 SUCCESS! + Save Offline Model1 SUCCESS! + ``` + + - 如果用户采用将TensorFlow原始模型解析为Graph的构图方式,请执行如下命令: + + 如果安装的是ATC组件,请执行:**./ir_build ${soc_version} tf** + + 如果安装的是FwkACLlib组件,请执行:**./fwk_ir_build ${soc_version} tf** + + 编译成功提示: + + ``` + ========== Generate graph from tensorflow origin model success.========== + Build Model1 SUCCESS! + Save Offline Model1 SUCCESS! + ``` + + - 如果用户采用将Caffe原始模型解析为Graph的构图方式,请执行如下命令: + + 如果安装的是ATC组件,请执行:**./ir_build ${soc_version} caffe** + + 如果安装的是FwkACLlib组件,请执行:**./fwk_ir_build ${soc_version} caffe** + + 编译成功提示: + + ``` + ========== Generate graph from caffe origin model success.========== + Build Model1 SUCCESS! + Save Offline Model1 SUCCESS! + ``` + +3. 检查执行结果。 + + 在**out**目录下生成离线模型文件。 diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/scripts/build.sh b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/scripts/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..84cbc783559617f960b17630d5831e5928f7a04b --- /dev/null +++ b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/scripts/build.sh @@ -0,0 +1,161 @@ +#!/bin/bash +# Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. + +export SCRIPT_PATH=$(cd "$(dirname $0)"; pwd) +export BASE_PATH="${SCRIPT_PATH}/.." +export BUILD_PATH="${BASE_PATH}/build" +CMAKE_X86_64_PATH="${BUILD_PATH}/x86_64" +CMAKE_AARCH64_PATH="${BUILD_PATH}/aarch64" + +clean=n +processor_type=aarch64 +UDF_TARGET_LIB=udf +UDF_TARGET=udf +execute_node=accelerator +compile_st=false + +while true +do + case "$1" in + -h | --help) + echo " --help show the help info of using this shell" + echo " --toolchain_dir=* specify cross compile toolchain directory, default is /usr/local/Ascend/latest/toolkit/toolchain/hcc" + echo " --processor_type=* specify target processor type, x86_64 or aarch64, default is aarch64" + echo " --execute_node=* specify execute node, head or accelerator, default is accelerator" + echo " --target_name=* specify target name, default is udf" + echo " -test compile test binary file" + echo " clean clean compile result directory" + exit 0 + ;; + clean) + clean=y + shift + ;; + --toolchain_dir=*) + tool_dir=`echo ${1} | cut -d"=" -f2` + export TOOLCHAIN_DIR=$tool_dir + echo "specified TOOLCHAIN_DIR=$TOOLCHAIN_DIR" + shift + ;; + --processor_type=*) + processor_type=`echo ${1} | cut -d"=" -f2` + echo "specified processor_type=$processor_type" + shift + ;; + --execute_node=*) + execute_node=`echo ${1} | cut -d"=" -f2` + echo "specified execute_node=$execute_node" + shift + ;; + --target_name=*) + target_name=`echo ${1} | cut -d"=" -f2` + echo "specified target_name=$target_name" + shift + ;; + -t | -test) + compile_st=true + shift + ;; + -*) + echo " --help show the help info of using this shell" + echo " --toolchain_dir=* specify cross compile toolchain directory, default is /usr/local/Ascend/latest/toolkit/toolchain/hcc" + echo " --processor_type=* specify target processor type, x86_64 or aarch64, default is aarch64" + echo " --execute_node=* specify execute node, head or accelerator, default is accelerator" + echo " --target_name=* specify target name, default is udf" + echo " -test ompile test binary file" + echo " clean clean compile result directory" + exit 0 + ;; + *) + break + ;; + esac +done + +log() { + cur_date=`date +"%Y-%m-%d %H:%M:%S"` + echo "[$cur_date] "$1 +} + +# clean compile result +if [ "x$clean" == "xy" ] 2>/dev/null; then + rm -rf ${BUILD_PATH} 2>/dev/null + log "[INFO] Clean successfully." + exit 0 +fi + +if [ ${compile_st} == "false" ]; then + export UDF_TARGET_LIB=$target_name +else + export UDF_TARGET=$target_name +fi + +mkdir -p ${BUILD_PATH} +cd ${BUILD_PATH} + +CMAKE_ARGS="-DCMAKE_SKIP_RPATH=TRUE" +if [ ${execute_node} == "head" ]; then + CMAKE_ARGS="${CMAKE_ARGS} -Dexecute_node=head" +elif [ ${execute_node} == "accelerator" ]; then + CMAKE_ARGS="${CMAKE_ARGS} -Dexecute_node=accelerator" +else + log "[ERROR] Invalid Para. use ./build.sh --help for more detial." + exit 1 +fi + +# for cross compiler +if [ ${processor_type} == "x86_64" ] +then + log "[INFO] x86_64 build." + mkdir -p ${CMAKE_X86_64_PATH} + cd "${CMAKE_X86_64_PATH}" + +elif [ ${processor_type} == "aarch64" ]; then + log "[INFO] aarch64 build." + CMAKE_ARGS="${CMAKE_ARGS} -DAARCH64=TRUE" + mkdir -p ${CMAKE_AARCH64_PATH} + cd "${CMAKE_AARCH64_PATH}" +else + log "[ERROR] Invalid Para. use ./build.sh --help for more detial." + exit 1 +fi + +if [ ${compile_st} == "false" ]; then + cmake ../../src ${CMAKE_ARGS} +else + cmake ../../st ${CMAKE_ARGS} +fi + +if [ $? -ne 0 ]; then + log "[ERROR] Please check cmake result." + exit 1 +fi + +# begin make +log "[INFO] Make begin." +make +if [ $? -ne 0 ]; then + log "[ERROR] Please check make result." + exit 1 +fi + +#copy build result to out directory. +cd ${BASE_PATH} +mkdir -p out +cd out +if [ ${processor_type} == "x86_64" ] +then + if [ ${compile_st} == "false" ]; then + cp $CMAKE_X86_64_PATH/lib$UDF_TARGET_LIB.so . + else + cp $CMAKE_X86_64_PATH/$UDF_TARGET . + fi + log "[INFO] Build successfully, the target is in $BASE_PATH/out." +else + if [ ${compile_st} == "false" ]; then + cp $CMAKE_AARCH64_PATH/lib$UDF_TARGET_LIB.so . + else + cp $CMAKE_AARCH64_PATH/$UDF_TARGET . + fi + log "[INFO] Build successfully, the target is in $BASE_PATH/out." +fi diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/src/CMakeLists.txt b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/src/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..05d490671f8392b91ecc9fd1e5d4334de830e2dd --- /dev/null +++ b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/src/CMakeLists.txt @@ -0,0 +1,83 @@ +cmake_minimum_required(VERSION 3.5) +project(UDF) +set(BASE_DIR + ${CMAKE_CURRENT_SOURCE_DIR} +) + +if(DEFINED ENV{TOOLCHAIN_DIR}) + set(TOOLCHAIN_DIR $ENV{TOOLCHAIN_DIR) +else() + set(TOOLCHAIN_DIR /usr/local/Ascend/latest/toolkit/toolchain/hcc) +endif() + +set(UDF_TARGET_LIB $ENV{UDF_TARGET_LIB}) + +set(INC_DIR + "${BASE_DIR}/../inc" +) +file(GLOB SRC_LIST "*.cpp") + + +if ("x${execute_node}" STREQUAL "xaccelerator") + add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1) +else() + add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) +endif() +#Specify cross compiler +if ("x${AARCH64}" STREQUAL "xTRUE") + if (NOT "x${TOOLCHAIN_DIR}" STREQUAL "x") + if (NOT IS_DIRECTORY ${TOOLCHAIN_DIR}) + message(FATAL_ERROR "specify cross compile toolchain directory(${TOOLCHAIN_DIR}) is not exist") + endif() + endif() + set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/aarch64-target-linux-gnu-g++) + set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/aarch64-target-linux-gnu-gcc) +else() + set(CMAKE_CXX_COMPILER g++) + set(CMAKE_C_COMPILER gcc) +endif() + +#================================== UDF so compile ==================================== +if ("x${SRC_LIST}" STREQUAL "x") + add_custom_target(${UDF_TARGET_LIB} + COMMAND echo "no source to make lib${UDF_TARGET_LIB}.so" + return(0) +endif() + +add_library(${UDF_TARGET_LIB} SHARED + ${SRC_LIST} +) + +target_include_directories(${UDF_TARGET_LIB} PRIVATE + ${INC_DIR} +) + +target_compile_options(${UDF_TARGET_LIB} PRIVATE + -O2 + -std=c++11 + -ftrapv + -fstack-protector-all + -fPIC +) + +if ("x${AARCH64}" STREQUAL "xTRUE") + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../lib/aarch64/libflow_func.so") + target_link_libraries(${UDF_TARGET_LIB} PRIVATE + -Wl,--whole-archive + ${CMAKE_CURRENT_SOURCE_DIR}/../lib/aarch64/libflow_func.so + -Wl,--no-whole-archive + ) + else() + message(FATAL_ERROR "Can not find libflow_func.so in environment. Please check the path of libflow_func.so is correct or not") + endif() +else() + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../lib/x86_64/libflow_func.so") + target_link_libraries(${UDF_TARGET_LIB} PRIVATE + -Wl,--whole-archive + ${CMAKE_CURRENT_SOURCE_DIR}/../lib/x86_64/libflow_func.so + -Wl,--no-whole-archive + ) + else() + message(FATAL_ERROR "Can not find libflow_func.so in environment. Please check the path of libflow_func.so is correct or not") + endif() +endif() diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/src/cast_flow_func.cpp b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/src/cast_flow_func.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e45e4ee4f7e80ad523bfe3434cd8ec6654936e8e --- /dev/null +++ b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/src/cast_flow_func.cpp @@ -0,0 +1,113 @@ +/** + * Copyright (C) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * Description: + */ +#include +#include "meta_flow_func.h" + +using namespace std; + +namespace FlowFunc{ +class CastFlowFunc : public MetaFlowFunc { +public: + CastFlowFunc() = default; + + ~CastFlowFunc() override = default; + + int32_t Init() override + { + auto getRet = context_->GetAttr("out_type", outDataType_); + if (getRet != FLOW_FUNC_SUCCESS) { + return getRet; + } + // just support cast to float and int64 + if ((outDataType_ != DataType::DT_FLOAT) && (outDataType_ != DataType::DT_INT64)) { + return -1; + } + return 0; + } + + template + void Cast(srcT *src, dstT *dst, size_t count) + { + for (size_t i = 0; i < count; ++i) { + dst[i] = static_cast(src[i]); + } + return; + } + + template + void Cast(T *src, void *dst, size_t count) + { + if (outDataType_ == DataType::DT_FLOAT) { + Cast(src, static_cast(dst), count); + } else if (outDataType_ == DataType::DT_INT64) { + Cast(src, static_cast(dst), count); + } + return; + } + + int32_t Proc(const std::vector> &inputTensors) override + { + // cast only have 1 input + if (inputTensors.size() != 1) { + return -1; + } + + auto inputTensor = inputTensors[0]; + // invalid input, trans to output + if (inputTensor->GetRetCode() != 0) { + auto ret = context_->SetOutput(0, inputTensor); + return ret; + } + + auto inputDataType = inputTensor->GetDataType(); + // type same + if (inputDataType == outDataType_) { + auto ret = context_->SetOutput(0, inputTensor); + return ret; + } + + auto &inputShape = inputTensor->GetShape(); + auto outputTensor = context_->AllocTensor(inputShape, outDataType_); + if (outputTensor == nullptr) { + return -1; + } + + auto dataSize = inputTensor->GetDataSize(); + if (dataSize == 0) { + return context_->SetOutput(0, outputTensor); + } + auto inputData = inputTensor->GetData(); + auto outputData = outputTensor->GetData(); + switch (inputDataType) { + case DataType::DT_FLOAT: + Cast(static_cast(inputData), outputData, dataSize / sizeof(float)); + break; + case DataType::DT_INT16: + Cast(static_cast(inputData), outputData, dataSize / sizeof(int16_t)); + break; + case DataType::DT_UINT16: + Cast(static_cast(inputData), outputData, dataSize / sizeof(uint16_t)); + break; + case DataType::DT_UINT32: + Cast(static_cast(inputData), outputData, dataSize / sizeof(uint32_t)); + break; + case DataType::DT_INT8: + Cast(static_cast(inputData), outputData, dataSize / sizeof(int8_t)); + break; + default: + // not support + outputTensor->SetRetCode(100); + break; + } + return context_->SetOutput(0, outputTensor); + } + +private: + DataType outDataType_; +}; + +REGISTER_FLOW_FUNC("Cast", CastFlowFunc); +} + diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/st/CMakeLists.txt b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/st/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2aa72de8163a51a4568d1fa1539938f2c6eafbd2 --- /dev/null +++ b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/st/CMakeLists.txt @@ -0,0 +1,86 @@ +cmake_minimum_required(VERSION 3.5.1) +project(UDF) +set(BASE_DIR + ${CMAKE_CURRENT_SOURCE_DIR} +) + +set(UDF_TARGET $ENV{UDF_TARGET}) +if(DEFINED ENV{TOOLCHAIN_DIR}) + set(TOOLCHAIN_DIR $ENV{TOOLCHAIN_DIR}) +else() + set(TOOLCHAIN_DIR /usr/local/Ascend/latest/toolkit/toolchain/hcc) +endif() + +set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY TRUE) +set(ASCEND_PATH /usr/local/Ascend/latest) + +set(FWK_INCLUDE_DIR ${ASCEND_PATH}/fwkacllib/include) +set(X86_64_LINUX_INCLUDE_DIR ${ASCEND_PATH}/x86_64-linux/include) + +file(GLOB SRC_LIST "*.cpp") + +if ("x${execute_node}" STREQUAL "xaccelerator") + add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1) +else() + add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) +endif() + +#Specify cross compiler +if ("x${AARCH64}" STREQUAL "xTRUE") + message(STATUS "TOOLCHAIN_DIR=${TOOLCHAIN_DIR}") + set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/aarch64-target-linux-gnu-g++) + set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/aarch64-target-linux-gnu-gcc) +else() + set(CMAKE_CXX_COMPILER g++) + set(CMAKE_C_COMPILER gcc) +endif() + +set(common_compile_options + -std=c++11 + -g + -Wall +) + +############ UDF ############ +add_executable(${UDF_TARGET} + ${SRC_LIST} +) + +target_compile_options(${UDF_TARGET} PRIVATE + ${common_compile_options} +) + +target_compile_definitions(${UDF_TARGET} PRIVATE + ${common_compile_definitions} +) + +target_include_directories(${UDF_TARGET} PRIVATE + ${ASCEND_PATH}/opp/op_proto/built-in/inc + ${FWK_INCLUDE_DIR}/graph + ${FWK_INCLUDE_DIR}/ge + ${FWK_INCLUDE_DIR}/parser + ${FWK_INCLUDE_DIR} + ${X86_64_LINUX_INCLUDE_DIR}/graph + ${X86_64_LINUX_INCLUDE_DIR}/ge + ${X86_64_LINUX_INCLUDE_DIR}/parser + ${X86_64_LINUX_INCLUDE_DIR} +) + +target_link_directories(${UDF_TARGET} PRIVATE + ${ASCEND_PATH}/fwkacllib/lib64/stub +) + +target_link_libraries(${UDF_TARGET} PRIVATE + -Wl,--no-as-needed + graph + ge_runner + fmk_parser + -Wl,--as-needed +) + +############ install ############ +set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_LIST_DIR}) + +install(TARGETS ${UDF_TARGET} OPTIONAL + RUNTIME DESTINATION output +) diff --git a/cplusplus/level1_single_api/3_ir/udf/UDFBuild/st/main.cpp b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/st/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3bd8c52af47a782376de4db3088a28b4aaac468f --- /dev/null +++ b/cplusplus/level1_single_api/3_ir/udf/UDFBuild/st/main.cpp @@ -0,0 +1,138 @@ +/** + * Copyright 2022 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "graph.h" +#include "types.h" +#include "tensor.h" +#include "attr_value.h" +#include "ge_error_codes.h" +#include "ge_api_types.h" +#include "ge_ir_build.h" +#include "ge_api.h" +#include "all_ops.h" +#include +#include +#include "data_flow_ops.h" + +using namespace std; +using namespace ge; +using ge::Operator; + +void PrepareOptions(std::map& options) { +} + +bool GenGraph(Graph& graph) +{ + auto shape_data = vector({ 1,2 }); + TensorDesc desc_data(ge::Shape(shape_data), FORMAT_ND, DT_FLOAT); + + // data op + auto data1 = op::Data("Data1").set_attr_index(0); + data1.update_input_desc_x(desc_data); + data1.update_output_desc_y(desc_data); + + auto result_output = op::FlowFunc("flowFunc1") + .set_attr_bin_path("../out/libudf.so") // so path + .set_attr_func_name("Cast") + .set_attr_output_types({DT_INT64}) + .create_dynamic_input_x(1) + .set_dynamic_input_x(0,data1) + .create_dynamic_output_y(1); + // set flow attr + result_output.SetAttr("_flow_attr", true); + result_output.SetAttr("_process_node_engine_id", "UDF"); + result_output.SetAttr("_processor_type", "x86_64"); + result_output.SetAttr("out_type", DT_INT64); + + + std::vector inputs{ data1 }; + std::vector outputs{ result_output }; + graph.SetInputs(inputs).SetOutputs(outputs); + + return true; +} + +int main(int argc, char* argv[]) +{ + ge::Status ret; + uint32_t graphId = 0; + std::vector input; + std::vector output; + float inputData1[2] = {1.1, 1.2}; + Tensor input1(TensorDesc(ge::Shape({2}), FORMAT_ND, DT_FLOAT), (uint8_t *)inputData1, 2 * sizeof(float)); + input.push_back(input1); + + // Generate graph + Graph graph1("IrGraph1"); + ret = GenGraph(graph1); + if (!ret) { + cout << "================= Generate Graph Failed! ================" << endl; + return -1; + } else { + cout << "================= Generate Graph Success! ================" << endl; + } + + const std::map config = { + {"device_id", "0"}, + {"rank_table_file", ""}, + {"ge.aicpuFlag", "1"}, + {"ge.graphRunMode", "2"}, + {"ge.exec.isAICPUMode", "1"}, + {"ge.DDK_version", "1.60.T17.B830"}, + + {"ge.feFlag", "1"}, + {"ge.opsProtoLibPath", "/usr/local/HiAI/runtime/ops/op_proto/built-in/"}, + {"ge.soLoadPath", "/usr/local/HiAI/runtime/lib64/plugin/opskernel/libaicpu_engine.so:/usr/local/HiAI/runtime/lib64/plugin/opskernel/libfe.so:/usr/local/HiAI/runtime/lib64/plugin/opskernel/libge_local_engine.so:/usr/local/HiAI/runtime/lib64/plugin/opskernel/librts_engine.so"}, + {"ge.exec.precision_mode", "allow_fp32_to_fp16"}, + {"ge.socVersion", "Ascend310P3"} + }; + ret = ge::GEInitialize(config); + std::map options; + ge::Session *session = new Session(options); + if (session == nullptr) { + cout << "Create Session Failed!" << endl; + return FAILED; + } + + ret = session->AddGraph(graphId, graph1); + if (ret != SUCCESS) { + cout << "========== Add Graph Failed! ==========" << endl; + return FAILED; + } + + ret = session->RunGraph(graphId, input, output); + if (ret != SUCCESS) { + cout << "========== Run Graph Failed! ==========" << endl; + return FAILED; + } + + ret = session->RemoveGraph(graphId); + if (ret != SUCCESS) { + cout << "========== Remove Graph Failed! ================" << endl; + return FAILED; + } + + ret = ge::GEFinalize(); + if (ret != SUCCESS) { + cout << "================= Finalize Graph Failed! ================" << endl; + return FAILED; + } + cout << "================= Finalize Graph Success! ================" << endl; + return SUCCESS; +}